home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume10 / tr2latex < prev    next >
Encoding:
Text File  |  1987-06-30  |  87.1 KB  |  3,580 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i032: Translate troff to LaTex
  5. Message-ID: <524@uunet.UU.NET>
  6. Date: 2 Jul 87 03:05:04 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 3569
  9. Approved: rs@uunet.uu.net
  10.  
  11. Mod.Sources: Volume 10, Number 32
  12. Submitted by: Kamal Al-Yahya <kamal@hanauma.stanford.edu>
  13. Archive-name: tr2latex
  14.  
  15. This program translates troff documents to latex.  You will notice that the
  16. translation is not always 100%, but it relieves one from manual translation,
  17. where the user might need to touch up on the translated document to customize
  18. the translation.
  19.  
  20. There is a testfile and a manual page in the package that can be used
  21. to test the translator.  Try some UNIX manual pages too.
  22.  
  23. #! /bin/sh
  24. # This is a shell archive, meaning:
  25. # 1. Remove everything above the #! /bin/sh line.
  26. # 2. Save the resulting text in a file.
  27. # 3. Execute the file with /bin/sh (not csh) to create the files:
  28. #    tr2tex.c
  29. #    tr.c
  30. #    subs.c
  31. #    setups.h
  32. #    simil.h
  33. #    greek.h
  34. #    flip.h
  35. #    forbid.h
  36. #    macros.h
  37. #    maths.h
  38. #    makefile
  39. #    makefile.msc
  40. #    troffms.sty
  41. #    troffman.sty
  42. #    tr2tex.9
  43. #    tr2tex.9-tex-orig
  44. #    README
  45. #    testfile
  46. #    testfile.tex-orig
  47. #    diffs.tex
  48. # This archive created: Sun Mar  8 12:05:26 1987
  49. export PATH; PATH=/bin:$PATH
  50. if test -f 'tr2tex.c'
  51. then
  52.     echo shar: will not over-write existing file "'tr2tex.c'"
  53. else
  54. cat << \SHAR_EOF > 'tr2tex.c'
  55. /* COPYRIGHT (C) 1987 Kamal Al-Yahya */
  56.  
  57. /* tr2tex: troff to tex translator */
  58. /* Author: Kamal Al-Yahya, Stanford University,        9/4/86 */
  59. /* Last modified:                    1/1/87 */
  60. /* Keyword: convert translate tex troff */
  61.  
  62. char *documentation[] = {
  63. " SYNTAX",
  64. "        tr2tex [-m] file1 file2 ...",
  65. "or",
  66. "        tr2tex [-m] < file1 file2 ...",
  67. "",
  68. " Use the -m flag for manual",
  69. "",
  70. };
  71.  
  72. int    doclength = { sizeof documentation/sizeof documentation[0] };
  73.  
  74. #include        "setups.h"
  75.  
  76. #ifdef tops20
  77. #define TEMPFILE "texXXXXXX"
  78. #else
  79. #define TEMPFILE "/tmp/texXXXXXX"
  80. #endif
  81.  
  82. FILE *out_file;
  83.  
  84. #if HAVE_SGTTY
  85. struct sgttyb ttystat;
  86. #endif
  87. extern char *mktemp();
  88. char scratch_file[MAXWORD];
  89.  
  90. int man;
  91. int xargc;
  92. char **xargv;
  93.  
  94. int
  95. main(argc,argv)
  96. int argc; 
  97. char *argv[];
  98. {
  99.  
  100. char *inbuf, *outbuf;
  101.  
  102. FILE *temp,*scr;
  103. register char *cptr;
  104. int piped_in;
  105. int i;
  106. long timeval;        /* clock value from time() for ctime()    */
  107. char *document = "article";            /* document type */
  108. char *options = "[troffms,11pt]";        /* style options */
  109.  
  110. /* Allocate large arrays dynamically to conserve stack space */
  111.  
  112. if (((inbuf = (char *)malloc(MAXLEN*sizeof(char))) == (char *)NULL) ||
  113.     ((outbuf = (char *)malloc(MAXLEN*sizeof(char))) == (char *)NULL))
  114.     {
  115.         fprintf(stderr,"tr2tex: Cannot malloc() internal buffer space\n\
  116. Need two arrays of %d characters each\n",MAXLEN);
  117.     exit(-1);
  118.     }
  119.  
  120. /* If no arguments, and not in a pipeline, self document */
  121. #if HAVE_SGTTY
  122. piped_in = ioctl ((fileno (stdin)), TIOCGETP, &ttystat);
  123. #else    /* if no sggty, it cannot distinguish piped input from no input */
  124. piped_in = (argc == 1);
  125. #endif
  126.  
  127. if (argc == 1 && !piped_in)
  128.     {
  129.     for( i=0; i<doclength; i++)
  130.         printf("%s\n",documentation[i]);
  131.     exit (0);
  132.     }
  133.  
  134. /* initialize spacing and indentation parameters */
  135. strcpy(linespacing.def_units,"\\normalbaselineskip");
  136. strcpy(linespacing.old_units,"\\normalbaselineskip");
  137. strcpy(indent.def_units,"em");        strcpy(indent.old_units,"em");
  138. strcpy(tmpind.def_units,"em");        strcpy(tmpind.old_units,"em");
  139. strcpy(space.def_units,"\\baselineskip");
  140. strcpy(space.old_units,"\\baselineskip");
  141. strcpy(vspace.def_units,"pt");        strcpy(vspace.old_units,"pt");
  142. linespacing.value = 1.;            linespacing.old_value = 1.;
  143. indent.value = 0.;            indent.old_value = 0.;
  144. tmpind.value = 0.;            tmpind.old_value = 0.;
  145. space.value = 1.;            space.old_value = 1.;
  146. vspace.value = 1.;            vspace.old_value = 1.;
  147. linespacing.def_value = 0;
  148. indent.def_value = 0;
  149. tmpind.def_value = 0;
  150. space.def_value = 1;
  151. vspace.def_value = 1;
  152.  
  153. out_file = stdout;        /* default output */
  154. math_mode = 0;            /* start with non-math mode */
  155. de_arg = 0;            /* not a .de argument */
  156.  
  157. /* process option flags */
  158. xargc = argc;
  159. xargv = argv;
  160. for (xargc--,xargv++; xargc; xargc--,xargv++)
  161.     {
  162.     cptr = *xargv; 
  163.     if( *cptr=='-' )
  164.         {
  165.         while( *(++cptr))
  166.             {
  167.             switch( *cptr )
  168.                 {
  169.                 case 'm':
  170.                     man = 1;
  171.                     strcpy(options,"[troffman]");
  172.                     break;
  173.                 default:
  174.                          fprintf(stderr,
  175.                         "tr2tex: unknown flag -%c\n",*cptr);
  176.                     break;
  177.                 }
  178.             }
  179.         }
  180.     }
  181. /* start of translated document */
  182.  
  183. timeval = time(0);
  184. fprintf(out_file,"%% -*-LaTeX-*-\n\
  185. %% Converted automatically from troff to LaTeX by tr2tex on %s",ctime(&timeval));
  186. fprintf(out_file,"%% tr2tex was written by Kamal Al-Yahya at Stanford University\n\
  187. %% (Kamal%%Hanauma@SU-SCORE.ARPA)\n\n\n");
  188.  
  189. /* document style and options */
  190. fprintf(out_file,"\\documentstyle%s{%s}\n\\begin{document}\n",options,document);
  191.  
  192. /* first process pipe input */
  193. if(piped_in)
  194.     {
  195. /* need to buffer; can't seek in pipes */
  196. /* make a temporary and volatile file */
  197.     strcpy(scratch_file,TEMPFILE);
  198.     mktemp(scratch_file);
  199.     if ((scr=fopen(scratch_file,"w")) == (FILE *)NULL)
  200.         {
  201.         fprintf(stderr,
  202.             "tr2tex: Cannot open scratch file [%s]\n",scratch_file);
  203.         exit(-1);
  204.         }
  205.     scrbuf(stdin,scr);
  206.     fclose(scr);
  207.     scr=fopen(scratch_file,"r");
  208.     unlink(scratch_file);
  209.     tmpbuf(scr,inbuf);
  210.     fclose(scr);
  211.     troff_tex(inbuf,outbuf,0,0);
  212.     fprintf(out_file,"%%\n%% input file: stdin\n%%\n");
  213.     fputs(outbuf,out_file);
  214.     }
  215.  
  216. /* then process input line for arguments and assume they are input files */
  217. xargc = argc;
  218. xargv = argv;
  219.  
  220. for (xargc--,xargv++; xargc; xargc--,xargv++)
  221.     {
  222.     cptr = *xargv; 
  223.     if( *cptr=='-' ) continue; /* this is a flag */
  224.     if((temp=fopen(cptr,"r")) != (FILE *)NULL)
  225.         {
  226.         tmpbuf(temp,inbuf);
  227.         fclose(temp);
  228.         troff_tex(inbuf,outbuf,0,0);
  229.         fprintf(out_file,"%%\n%% input file: %s\n%%\n",cptr);
  230.         fputs(outbuf,out_file);
  231.         }
  232.     else
  233.         fprintf(stderr,"tr2tex: Cannot open %s\n",cptr);
  234.     }
  235. /* close translated document */
  236. fputs("\\end{document}\n",out_file);
  237.  
  238. exit(0);
  239. }
  240. SHAR_EOF
  241. fi # end of overwriting check
  242. if test -f 'tr.c'
  243. then
  244.     echo shar: will not over-write existing file "'tr.c'"
  245. else
  246. cat << \SHAR_EOF > 'tr.c'
  247. /* COPYRIGHT (C) 1987 Kamal Al-Yahya */
  248.  
  249. /*
  250. This program has the HARD-WIRED rules of the translator.
  251. It should handled with care.
  252. */
  253.  
  254. #define IN_TR  1
  255. #include        "setups.h"
  256. int def_count = 0;
  257. int mydef_count = 0;
  258.  
  259. void
  260. troff_tex(inbuf,outbuf,mid,rec)
  261. char *inbuf,*outbuf;
  262. int mid,rec;
  263. {
  264. char eqn_no[MAXWORD], w[MAXWORD], ww[MAXLINE], tmp[MAXWORD], tmp2[MAXWORD];
  265. char *p;
  266. int len,c,c1,c2,i,j;
  267. int ref = 0;
  268. int put_brace = 0;
  269. int first_word = 1;
  270. int no_word = 1;
  271. int arg = 0;
  272. int par = 0;
  273. int illegal = 0;
  274. int floating = 0;
  275. static int delim_defd = 0;    /* whether math delimiter has been defined */
  276. static char *DELIM = "$";
  277. float flen;
  278. int N;
  279. int RSRE = 0;            /* block indentation */
  280. int thisfont = 1;        /* default font is roman */
  281. int lastfont = 1;        /* default last font is roman */
  282. int offset = 0;            /* amount to offset inbuf */
  283. extern man;            /* man flag */
  284.  
  285. *outbuf = NULL;        w[0] = NULL;    ww[0] = NULL;
  286. tmp[0] = NULL;        tmp2[0] = NULL;
  287. while (*inbuf != NULL)
  288.     {
  289.     len = getword(inbuf,w);
  290.     c1 = *--inbuf;
  291.     c2 = *++inbuf;
  292.     inbuf += len;
  293.     if (isspace(w[0]) == 0)        no_word = 0;
  294. /* first check if we are in math mode */
  295.     if (math_mode)
  296.         {
  297.         len = get_till_space(inbuf,ww);
  298.         sprintf(tmp,"%s%s",w,ww);
  299.         if (strcmp(w,"delim") == 0)
  300.             {
  301.             delim_defd = 1;
  302.             inbuf += skip_white(inbuf);
  303.             DELIM[0] = *inbuf;
  304.             inbuf = skip_line(inbuf);
  305.             }
  306. /* check if it is a math delimiter; switch to non-math mode if so */
  307.         else if (delim_defd && strcmp(w,DELIM) == 0)
  308.             {
  309.             math_mode = 0;
  310.             *outbuf++ = '$';
  311.             }
  312. /* check for illegal macros here */
  313.         else if (len > 0 && def_count > 0 && (i=is_def(tmp)) >= 0)
  314.             {
  315.             inbuf += len;
  316.             outbuf = strapp(outbuf,def[i].replace);
  317.             }
  318. /* See if it is a (legally) defined macro */
  319.         else if (def_count > 0 && (i=is_def(w)) >= 0)
  320.             {
  321.             if (def[i].illegal)
  322.                 outbuf = strapp(outbuf,def[i].replace);
  323.             else
  324.                 {
  325.                 outbuf = strapp(outbuf,"\\");
  326.                 outbuf = strapp(outbuf,w);
  327.                 }
  328.             }
  329. /* Search for commands in some order; start with non-alphanumeric symbols */
  330.         else if (strcmp(w,"#") == 0 || strcmp(w,"&") == 0
  331.              || strcmp(w,"%") == 0 || strcmp(w,"_") == 0)
  332.             {
  333.             outbuf = strapp(outbuf,"\\");
  334.             outbuf = strapp(outbuf,w);
  335.             }
  336.         else if (strcmp(w,"=") == 0)
  337.             {
  338.             if (*inbuf == '=')
  339.                 {
  340.                 inbuf++;
  341.                 outbuf = strapp(outbuf,"\\equiv");
  342.                 }
  343.             else
  344.                 outbuf = strapp(outbuf,"=");
  345.             }
  346.         else if (strcmp(w,"<") == 0 || strcmp(w,">") == 0)
  347.             {
  348.             if (*inbuf == '=')
  349.                 {
  350.                 inbuf++;
  351.                 if (strcmp(w,"<") == 0)
  352.                     outbuf = strapp(outbuf,"\\le");
  353.                 else
  354.                     outbuf = strapp(outbuf,"\\ge");
  355.                 }
  356.             }
  357.         else if (strcmp(w,"-") == 0)
  358.             {
  359.             if (*inbuf == '>')
  360.                 {
  361.                 inbuf++;
  362.                 outbuf = strapp(outbuf,"\\to");
  363.                 }
  364.             else if (*inbuf == '+')
  365.                 {
  366.                 inbuf++;
  367.                 outbuf = strapp(outbuf,"\\mp");
  368.                 }
  369.             else
  370.                 *outbuf++ = '-';
  371.             }
  372.         else if (strcmp(w,"+") == 0)
  373.             {
  374.             if (*inbuf == '-')
  375.                 {
  376.                 inbuf++;
  377.                 outbuf = strapp(outbuf,"\\pm");
  378.                 }
  379.             else
  380.                 *outbuf++ = '+';
  381.             }
  382.         else if (strcmp(w,"\"") == 0)
  383.             {
  384.             len = get_no_math(inbuf,ww);
  385.             inbuf += len+1;
  386.             if (len > 1)
  387.                 {
  388.                 sprintf(tmp,"\\ \\it\\hbox{%s}",ww);
  389.                 outbuf = strapp(outbuf,tmp);
  390.                 }
  391.             else if (len == 1)
  392.                 *outbuf++ = ww[0];
  393.             }
  394. /* Now search for symbols that start with a captial */
  395.         else if (strcmp(w,".EN") == 0)
  396.             {
  397.             math_mode = 0;
  398.             if ((len=strlen(eqn_no)) > 0)
  399.                 {
  400.                 sprintf(tmp,"\\eqno %s",eqn_no);
  401.                 outbuf = strapp(outbuf,tmp);
  402.                 }
  403.             eqn_no[0] = NULL;
  404.             c1 = *--outbuf;
  405.             c2 = *--outbuf;
  406.             if (c1 == '\n' && c2 == '$')
  407.                 *--outbuf = NULL;
  408.             else
  409.                 {
  410.                 outbuf += 2;
  411.                 outbuf = strapp(outbuf,"$$");
  412.                 }
  413.             }
  414. /* Now search for symbols that start with a small letter */
  415.         else if (strcmp(w,"bold") == 0 || strcmp(w,"roman") == 0 ||
  416.              strcmp(w,"italic") == 0)
  417.             {
  418.             inbuf += get_arg(inbuf,ww,1);
  419.             if (strcmp(w,"bold") == 0)
  420.                 {
  421.                 sprintf(tmp,"{\\bf %s}",ww);
  422.                 outbuf = strapp(outbuf,tmp);
  423.                 }
  424.             else if (strcmp(w,"roman") == 0)
  425.                 {
  426.                 sprintf(tmp,"{\\rm %s}",ww);
  427.                 outbuf = strapp(outbuf,tmp);
  428.                 }
  429.             else
  430.                 {
  431.                 sprintf(tmp,"{\\it %s}",ww);
  432.                 outbuf = strapp(outbuf,tmp);
  433.                 }
  434.             }
  435.         else if (strcmp(w,"define") == 0)
  436.             {
  437.             if (def_count >= MAXDEF)
  438.                 {
  439.                 fprintf(stderr,
  440.                     "Too many defines. MAXDEF=%d\n",MAXDEF);
  441.                 exit(-1);
  442.                 }
  443.             for (i=0; *--outbuf != '$' && i < MAXLEN; i++)
  444.                 tmp[i] = *outbuf;
  445.             tmp[i] = NULL;
  446.             strcat(tmp,"$$");
  447.             *--outbuf = NULL;
  448.             inbuf += skip_white(inbuf);
  449.             inbuf += get_defword(inbuf,w,&illegal);
  450.             inbuf += skip_white(inbuf);
  451.             inbuf += getdef(inbuf,ww);
  452.             if (illegal)
  453.                 {
  454.                 def[def_count].illegal = 1;
  455.                 fprintf(stderr,
  456.                     "illegal TeX macro, %s, replacing it\n",w);
  457.                 p = (char *)malloc((unsigned)(strlen(ww)+1)*
  458.                     sizeof(char));
  459.                 strcpy(p,ww);
  460.                 def[def_count].replace = p;
  461.                 }
  462.             else
  463.                 {
  464.                 def[def_count].illegal = 0;
  465.                 sprintf(tmp2,"\\def\\%s{%s}\n",w,ww);
  466.                 outbuf = strapp(outbuf,tmp2);
  467.                 }
  468.             p = (char *)malloc((unsigned)(strlen(w)+1)*sizeof(char));
  469.             strcpy(p,w);
  470.             def[def_count++].def_macro = p;
  471.             inbuf += skip_white(inbuf);
  472.             for (j=i+1; j >= 0; j--)
  473.                 *outbuf++ = tmp[j];
  474.             tmp[0] = NULL;
  475.             }
  476.         else if (strcmp(w,"gsize") == 0 || strcmp(w,"gfont") == 0)
  477.             inbuf = skip_line(inbuf);
  478.         else if (strcmp(w,"left") == 0 || strcmp(w,"right") == 0)
  479.             {
  480.             sprintf(tmp,"\\%s",w);
  481.             outbuf = strapp(outbuf,tmp);
  482.             inbuf += skip_white(inbuf);
  483.             len = getword(inbuf,ww);
  484.             if (strcmp(ww,"floor") == 0)
  485.                 {
  486.                 inbuf += len;
  487.                 if (strcmp(w,"left") == 0)
  488.                     outbuf = strapp(outbuf,"\\lfloor");
  489.                 else
  490.                     outbuf = strapp(outbuf,"\\rfloor");
  491.                 }
  492.             else if (strcmp(ww,"nothing") == 0 || ww[0] == '\"')
  493.                 {
  494.                 inbuf += len;
  495.                 *outbuf++ = '.';
  496.                 if (ww[0] == '\"')    inbuf++;
  497.                 }
  498.             else if (*inbuf == '{' || *inbuf == '}')
  499.                 *outbuf++ = '\\';
  500.             }
  501.         else if (strcmp(w,"over") == 0)
  502.             {
  503.             if (!first_word)
  504.                 {
  505.                 outbuf--;
  506.                 for (i=0; *outbuf == ' ' || *outbuf == '\t' ||
  507.                         *outbuf =='\n'; i++)
  508.                     tmp[i] = *outbuf--;
  509.                 if (*outbuf == '}' && put_brace == 0)
  510.                     *outbuf = ' ';
  511.                 else
  512.                     {
  513.                     for (; !(*outbuf == ' ' || *outbuf == '\t'
  514.                     || *outbuf =='\n' || *outbuf == '$'); i++)
  515.                         tmp[i] = *outbuf--;
  516.                     put_brace = 0;
  517.                 *++outbuf = '{';
  518.                     }
  519.                 for (j=i-1; j >= 0; j--)
  520.                     *++outbuf = tmp[j];
  521.             *++outbuf = NULL;
  522.                 }
  523.             outbuf = strapp(outbuf,"\\over");
  524.             inbuf += skip_white(inbuf);
  525.             *outbuf++ = ' ';
  526.             if (*inbuf == '{')
  527.                 inbuf++;
  528.             else
  529.                 {
  530.                 inbuf = get_over_arg(inbuf,ww);
  531.                 outbuf = strapp(outbuf,ww);
  532.                 if (*inbuf != NULL || !first_word)
  533.                     *outbuf++ = '}';
  534.                 }
  535.             }
  536.         else if (strcmp(w,"size") == 0)
  537.             inbuf += get_arg(inbuf,ww,0);
  538.         else if (strcmp(w,"sup") == 0 || strcmp(w,"to") == 0 ||
  539.              strcmp(w,"sub") == 0 || strcmp(w,"from") == 0)
  540.             {
  541.             while ((c = *--outbuf) == ' ' || c == '\t' || c == '\n') ;
  542.             *++outbuf = NULL;
  543.             if (strcmp(w,"sup") == 0 || strcmp(w,"to") == 0)
  544.                 outbuf = strapp(outbuf,"^");
  545.             else
  546.                 outbuf = strapp(outbuf,"_");
  547.             inbuf += skip_white(inbuf);
  548.             len = get_sub_arg(inbuf,ww);
  549.             inbuf += len;
  550.             if (len > 1)
  551.                 {
  552.                 sprintf(tmp,"{%s}",ww);
  553.                 outbuf = strapp(outbuf,tmp);
  554.                 len = skip_white(inbuf);
  555.                 inbuf += len;
  556.                 (void) getword(inbuf,ww);
  557.                 if (strcmp(ww,"over") == 0)
  558.                     put_brace = 1;
  559.                 inbuf -= len;
  560.                 }
  561.             else
  562.                 outbuf = strapp(outbuf,ww);
  563.             }
  564.         else if (strcmp(w,"up") == 0 || strcmp(w,"down") == 0
  565.              || strcmp(w,"fwd") == 0 || strcmp(w,"back") == 0)
  566.             {
  567.             if (strcmp(w,"up") == 0)
  568.                 {
  569.                 outbuf = strapp(outbuf,"\\raise");
  570.                 strcpy(tmp,"ex");
  571.                 }
  572.             else if (strcmp(w,"down") == 0)
  573.                 {
  574.                 outbuf = strapp(outbuf,"\\lower");
  575.                 strcpy(tmp,"ex");
  576.                 }
  577.             else if (strcmp(w,"fwd") == 0)
  578.                 {
  579.                 outbuf = strapp(outbuf,"\\kern");
  580.                 strcpy(tmp,"em");
  581.                 }
  582.             else if (strcmp(w,"back") == 0)
  583.                 {
  584.                 outbuf = strapp(outbuf,"\\kern-");
  585.                 strcpy(tmp,"em");
  586.                 }
  587.             inbuf += skip_white(inbuf);
  588.             inbuf += getword(inbuf,ww);
  589.             len = atoi(ww);        flen = len/100.;
  590.             ww[0] = NULL;
  591.             sprintf(tmp2,"%4.2f%s",flen,tmp);
  592.             outbuf = strapp(outbuf,tmp2);
  593.             }
  594. /* Now check if the word is a member of a group */
  595.         else if (CAP_GREEK(w) > 0)
  596.             {
  597.             GR_to_Greek(w,ww);
  598.             outbuf = strapp(outbuf,ww);
  599.             }
  600.         else if (is_flip(w) >= 0)
  601.             {
  602.             if (!first_word)
  603.                 {
  604.                 len = skip_white(inbuf);
  605.                 inbuf += len;
  606.                 (void) getword(inbuf,ww);
  607.                 if (is_flip(ww) >= 0)
  608.                     {
  609.                     inbuf += strlen(ww);
  610.                     outbuf = flip_twice(outbuf,w,ww);
  611.                     }
  612.                 else
  613.                     {
  614.                     inbuf -= len;
  615.                     outbuf = flip(outbuf,w);
  616.                     }
  617.                 }
  618.             else
  619.                 {
  620.                 outbuf = strapp(outbuf,"\\");
  621.                 outbuf = strapp(outbuf,w);
  622.                 }
  623.             }
  624.         else if (is_mathcom(w,ww) >=0 )
  625.             outbuf = strapp(outbuf,ww);
  626.         else if (similar(w) > 0)
  627.             {
  628.             outbuf = strapp(outbuf,"\\");
  629.             outbuf = strapp(outbuf,w);
  630.             }
  631.  
  632. /* if none of the above math commands matched, it is an ordinary symbol;
  633.    just copy it */
  634.  
  635.         else    outbuf = strapp(outbuf,w);
  636.         }
  637.  
  638. /* check if it is a math delimiter; switch to math mode if so */
  639.  
  640.     else if (strcmp(w,"$") == 0 && de_arg > 0)
  641.         {
  642.         de_arg++;
  643.         *outbuf++ = '#';
  644.         }
  645.     else if (delim_defd && strcmp(w,DELIM) == 0)
  646.         {
  647.         math_mode = 1;
  648.         *outbuf++ = '$';
  649.         }
  650.     else if (strcmp(w,"$") == 0)
  651.         outbuf = strapp(outbuf,"\\$");
  652.  
  653. /* check if it is a non-math troff command */
  654.  
  655.     else if ((c2 == '.') && !(mid) && (c1 == '\n' || (first_word)))
  656.         {
  657. /* Search in some order; start with non-alphanumeric characters */
  658.         if (strcmp(w,".") == 0)
  659.             {
  660.             c1 = *inbuf;
  661.             c2 = *++inbuf;
  662.             if (c1 == '\\' && c2 == '\"')
  663.                 {
  664.                 ++inbuf;
  665.                 inbuf += get_line(inbuf,ww,0);
  666.                 outbuf = strapp(outbuf,"%");
  667.                 outbuf = strapp(outbuf,ww);
  668.                 }
  669.             else
  670.                 {
  671.                 fprintf(stderr,
  672.                 "I cannot translate troff macro .%c%c\n",c1,c2);
  673.                 inbuf += get_line(inbuf,ww,0);
  674.                 sprintf(tmp,"%%.%c%c",c1,c2);
  675.                 outbuf = strapp(outbuf,tmp);
  676.                 outbuf = strapp(outbuf,ww);
  677.                 if (*inbuf == NULL)    *outbuf++ = '\n';
  678.                 }
  679.             }
  680. /* Now search for commads that start with a capital */
  681.         else if (strcmp(w,".AB") == 0)
  682.             {
  683.             inbuf += get_arg(inbuf,ww,0);
  684.             if (strcmp(ww,"no") == 0)
  685.                 outbuf = strapp(outbuf,"\\bigskip");
  686.             else
  687.                 outbuf = strapp(outbuf,"\\begin{abstract}");
  688.             }
  689.         else if (strcmp(w,".B") == 0 || strcmp(w,".bf") == 0 ||
  690.              strcmp(w,".I") == 0 || strcmp(w,".it") == 0 ||
  691.              strcmp(w,".R") == 0 || strcmp(w,".rm") == 0)
  692.             {
  693.             if (strcmp(w,".R") == 0 || strcmp(w,".rm") == 0)
  694.                 strcpy(w,"rm");
  695.             else if (strcmp(w,".B") == 0 || strcmp(w,".bf") == 0)
  696.                 strcpy(w,"bf");
  697.             else
  698.                 strcpy(w,"it");
  699.             inbuf += get_arg(inbuf,ww,1);
  700.             if (ww[0] == NULL)
  701.                 {
  702.                 outbuf = strapp(outbuf,"\\");
  703.                 outbuf = strapp(outbuf,w);
  704.                 }
  705.             else
  706.                 {
  707.                 sprintf(tmp,"{\\%s %s}",w,ww);
  708.                 outbuf = strapp(outbuf,tmp);
  709.                 }
  710.             }
  711.         else if (man && (strcmp(w,".BR") == 0 || strcmp(w,".BI") == 0
  712.              || strcmp(w,".IR") == 0 || strcmp(w,".IB") == 0 ||
  713.              strcmp(w,".RI") == 0 || strcmp(w,".RB") == 0))
  714.             {
  715.             outbuf = alternate(inbuf,outbuf,w);
  716.             inbuf = skip_line(inbuf);
  717.             *outbuf++ = '\n';
  718.             }
  719.         else if (strcmp(w,".BX") == 0)
  720.             {
  721.             inbuf += get_arg(inbuf,ww,1);
  722.             sprintf(tmp,"\\fbox{%s}",ww);
  723.             outbuf = strapp(outbuf,tmp);
  724.             }
  725.         else if (strcmp(w,".EQ") == 0)
  726.             {
  727.             math_mode = 1;
  728.             put_brace = 0;
  729.             outbuf = strapp(outbuf,"$$");
  730.             len = get_arg(inbuf,eqn_no,0);
  731.             if (strcmp(eqn_no,"I") == 0 || strcmp(eqn_no,"L") == 0)
  732.                 {
  733.                 fprintf(stderr,"lineups are ignored\n");
  734.                 inbuf += len;
  735.                 len = get_arg(inbuf,eqn_no,0);
  736.                 }
  737.             if ((strlen(eqn_no)) > 0)
  738.                 inbuf += len;
  739.             len = get_arg(inbuf,tmp,0);
  740.             if (strcmp(tmp,"I") == 0 || strcmp(tmp,"L") == 0)
  741.                 {
  742.                 fprintf(stderr,"lineups are ignored\n");
  743.                 inbuf += len;
  744.                 }
  745.             }
  746.         else if (strcmp(w,".IP") == 0)
  747.             {
  748.             inbuf += get_arg(inbuf,ww,1);
  749.             inbuf = skip_line(inbuf);
  750.             if (IP_stat == 0)
  751.                 outbuf = strapp(outbuf,"\\begin{itemize}\n");
  752.             sprintf(tmp,"\\item[{%s}]\n",ww);
  753.             outbuf = strapp(outbuf,tmp);
  754.             if (de_arg > 0)        mydef[mydef_count].par = 2;
  755.             else            IP_stat = 1;
  756.             }
  757.         else if (strcmp(w,".KE") == 0)
  758.             {
  759.             if (floating)
  760.                 outbuf = strapp(outbuf,"\\end{figure}");
  761.             else
  762.                 outbuf = strapp(outbuf,"}");
  763.             floating = 0;
  764.             }
  765.         else if (strcmp(w,".KF") == 0)
  766.             {
  767.             floating = 1;
  768.             outbuf = strapp(outbuf,"\\begin{figure}");
  769.             }
  770.         else if (strcmp(w,".QP") == 0)
  771.             {
  772.             if (de_arg > 0)        mydef[mydef_count].par = 4;
  773.             else            QP_stat = 1;
  774.             outbuf = strapp(outbuf,"\\begin{quotation}");
  775.             }
  776.         else if (strcmp(w,".RE") == 0)
  777.             {
  778.             RSRE--;
  779.             if (RSRE < 0)
  780.                 fprintf(stderr,".RS with no matching .RE\n");
  781.             sprintf(tmp,"\\ind{%d\\parindent}",RSRE);
  782.             outbuf = strapp(outbuf,tmp);
  783.             }
  784.         else if (strcmp(w,".RS") == 0)
  785.             {
  786.             RSRE++;
  787.             sprintf(tmp,"\\ind{%d\\parindent}",RSRE);
  788.             outbuf = strapp(outbuf,tmp);
  789.             }
  790.         else if (strcmp(w,".Re") == 0)
  791.             {
  792.             if (ref == 0)
  793.                 outbuf = strapp(outbuf,"\\REF\n");
  794.             ref++;
  795.             inbuf = skip_line(inbuf);
  796.             inbuf += get_ref(inbuf,ww);
  797.             sprintf(tmp,"\\reference{%s}",ww);
  798.             outbuf = strapp(outbuf,tmp);
  799.             }
  800.         else if (man && (strcmp(w,".TP") == 0 || strcmp(w,".HP") == 0))
  801.             {
  802.             if (IP_stat && TP_stat)
  803.                 {
  804.                 outbuf = strapp(outbuf,"\\end{itemize}%\n");
  805.                 IP_stat = 0;
  806.                 }
  807.             if (QP_stat && TP_stat)
  808.                 {
  809.                 outbuf = strapp(outbuf,"\\end{quotation}%\n");
  810.                 QP_stat = 0;
  811.                 }
  812.             inbuf = skip_line(inbuf);
  813.             inbuf += get_line(inbuf,ww,1);
  814.             if (TP_stat == 0)
  815.                 {
  816.                 sprintf(tmp,"\\begin{TPlist}{%s}\n",ww);
  817.                 outbuf = strapp(outbuf,tmp);
  818.                 }
  819.             sprintf(tmp,"\\item[{%s}]",ww);
  820.             outbuf = strapp(outbuf,tmp);
  821.             if (de_arg > 0)        mydef[mydef_count].par = 3;
  822.             else            TP_stat = 1;
  823.             }
  824.         else if (man && (strcmp(w,".TH") == 0))
  825.             {
  826. /* expect something like .TH LS 1 "September 4, 1985"*/
  827.             outbuf = strapp(outbuf,"\\phead");
  828.             for (j = 1; j <= 3; ++j)
  829.                 {
  830.                 inbuf += get_arg(inbuf,ww,0);
  831.                 sprintf(tmp,"{%s}",ww);
  832.                 outbuf = strapp(outbuf,tmp);
  833.                 }
  834.             *outbuf++ = '\n';
  835.             }
  836.         else if (strcmp(w,".TS") == 0)
  837.             {
  838.             fprintf(stderr,"I am not very good at tables\n\
  839. I can only do very simple ones. You may need to check what I've done\n");
  840.             inbuf = skip_line(inbuf);
  841.             outbuf = do_table(inbuf,outbuf,&offset);
  842.             inbuf += offset;
  843.             offset = 0;        /* reset */
  844.             }
  845. /* Now search for commands that start with small letters */
  846.         else if (strcmp(w,".TE") == 0)
  847.             {
  848.             fprintf(stderr,"Oops! I goofed. I told you I am not very good at tables.\nI have encountered a table end but I am not in table mode\n");
  849.             }
  850.         else if (strcmp(w,".de") == 0)
  851.             {
  852.             de_arg = 1;
  853.             if (mydef_count >= MAXDEF)
  854.                 {
  855.                 fprintf(stderr,
  856.                     "Too many .de's. MAXDEF=%d\n",MAXDEF);
  857.                 exit(-1);
  858.                 }
  859.             inbuf += skip_white(inbuf);
  860.             inbuf += get_defword(inbuf,w,&illegal);
  861.             inbuf += skip_white(inbuf);
  862.             inbuf += get_mydef(inbuf,ww);
  863.             mydef[mydef_count].arg_no = de_arg;
  864.             if (illegal)
  865.                 {
  866.                 mydef[mydef_count].illegal = 1;
  867.                 fprintf(stderr,
  868.                     "illegal TeX macro, %s, replacing it\n",w);
  869.                 p = (char *)malloc((unsigned)(strlen(ww)+2)*
  870.                     sizeof(char));
  871.                 sprintf(p,"%s",ww);
  872.                 mydef[mydef_count].replace = p;
  873.                 }
  874.             else
  875.                 {
  876.                 mydef[mydef_count].illegal = 0;
  877.                 sprintf(tmp,"\\def\\%s",w);
  878.                 outbuf = strapp(outbuf,tmp);
  879.                 for (j=1; j<de_arg; j++)
  880.                     {
  881.                     sprintf(tmp,"#%d",j);
  882.                     outbuf = strapp(outbuf,tmp);
  883.                     }
  884.                 sprintf(tmp,"{%s}\n",ww);
  885.                 outbuf = strapp(outbuf,tmp);
  886.                 }
  887.             p = (char *)malloc((unsigned)(strlen(w)+2)*sizeof(char));
  888.             sprintf(p,".%s",w);
  889.             mydef[mydef_count++].def_macro = p;
  890.             inbuf = skip_line(inbuf);
  891.             de_arg = 0;
  892.             }
  893.         else if (strcmp(w,".ds") == 0)
  894.             {
  895.             inbuf += get_arg(inbuf,w,0);
  896.             inbuf += skip_white(inbuf);
  897.             inbuf += get_line(inbuf,ww,1);
  898.             if (strcmp(w,"LH") == 0)
  899.                 {
  900.                 sprintf(tmp,"\\lefthead{%s}",ww);
  901.                 outbuf = strapp(outbuf,tmp);
  902.                 }
  903.             else if (strcmp(w,"RH") == 0)
  904.                 {
  905.                 sprintf(tmp,"\\righthead{%s}",ww);
  906.                 outbuf = strapp(outbuf,tmp);
  907.                 }
  908.             else if (strcmp(w,"CF") == 0)
  909.                 {
  910.                 if (index(ww,'%') == 0)
  911.                     {
  912.                     sprintf(tmp,"\\footer{%s}",ww);
  913.                     outbuf = strapp(outbuf,tmp);
  914.                     }
  915.                 else
  916.                     outbuf = strapp(outbuf,
  917.                             "\\footer{\\rm\\thepage}");
  918.                 }
  919.             else
  920.                 {
  921.                 fprintf(stderr,"I do not understand .ds %s\n",w);
  922.                 sprintf(tmp,"%%.ds %s %s",w,ww);
  923.                 outbuf = strapp(outbuf,tmp);
  924.                 }
  925.             }
  926.         else if (strcmp(w,".sp") == 0)
  927.             {
  928.             inbuf += get_arg(inbuf,ww,0);
  929.             (void) get_size(ww,&space);
  930.             sprintf(tmp,"\\par\\vspace{%3.1f%s}",
  931.                 space.value,space.units);
  932.             outbuf = strapp(outbuf,tmp);
  933.             }
  934.         else if (strcmp(w,".in") == 0)
  935.             {
  936.             inbuf += get_arg(inbuf,ww,0);
  937.             (void) get_size(ww,&indent);
  938.             sprintf(tmp,"\\ind{%3.1f%s}",indent.value,indent.units);
  939.             outbuf = strapp(outbuf,tmp);
  940.             }
  941.         else if (strcmp(w,".ls") == 0)
  942.             {
  943.             inbuf += get_arg(inbuf,ww,0);
  944.             (void) get_size(ww,&linespacing);
  945.             sprintf(tmp,"\\baselineskip=%3.1f%s",linespacing.value,
  946.                     linespacing.units);
  947.             outbuf = strapp(outbuf,tmp);
  948.             }
  949.         else if (strcmp(w,".so") == 0)
  950.             {
  951.             inbuf += get_arg(inbuf,ww,0);
  952.             sprintf(tmp,"\\input %s",ww);
  953.             outbuf = strapp(outbuf,tmp);
  954.             }
  955.         else if (strcmp(w,".ti") == 0)
  956.             {
  957.             inbuf += get_arg(inbuf,ww,0);
  958.             tmpind.value = indent.value;
  959.             strcpy(tmpind.units,indent.units);
  960.             (void) get_size(ww,&tmpind);
  961.             sprintf(tmp,"\\tmpind{%3.1f%s}",
  962.                 tmpind.value,tmpind.units);
  963.             outbuf = strapp(outbuf,tmp);
  964.             }
  965.         else if (strcmp(w,".vs") == 0)
  966.             {
  967.             inbuf += get_arg(inbuf,ww,0);
  968.             (void) get_size(ww,&vspace);
  969.             sprintf(tmp,"\\par\\vspace{%3.1f%s}",
  970.                 vspace.value,vspace.units);
  971.             outbuf = strapp(outbuf,tmp);
  972.             }
  973. /* check if it is a member of a group */
  974.         else if (mydef_count > 0 && (i=is_mydef(w)) >= 0)
  975.             {
  976.             if (mydef[i].par > 0)
  977.                 {
  978.                 if (de_arg > 0)
  979.                     mydef[mydef_count].par = mydef[i].par;
  980.                 else
  981.                     {
  982.                     outbuf = end_env(outbuf);
  983.                     outbuf = strapp(outbuf,"\n");
  984.                     }
  985.                 }
  986.             if (mydef[i].illegal)
  987.                 outbuf = strapp(outbuf,mydef[i].replace);
  988.             else
  989.                 {
  990.                 w[0] = '\\';    /* replace dot by backslash */
  991.                 outbuf = strapp(outbuf,w);
  992.                 }
  993.             for (j=1; j <mydef[i].arg_no; j++)
  994.                 {
  995.                 inbuf += get_arg(inbuf,ww,1);
  996.                 sprintf(tmp,"{%s}",ww);
  997.                 outbuf = strapp(outbuf,tmp);
  998.                 }
  999.             if (de_arg == 0)    envoke_stat(mydef[i].par);
  1000.             }
  1001.         else if ((i=is_troff_mac(w,ww,&arg,&par)) >= 0)
  1002.             {
  1003.             if (par > 0)
  1004.                 {
  1005.                 if (de_arg > 0)    mydef[mydef_count].par = par;
  1006.                 else        outbuf = end_env(outbuf);
  1007.                 }
  1008.             outbuf = strapp(outbuf,ww);
  1009.             if (ww[0] == NULL)
  1010.                 inbuf = skip_line(inbuf);
  1011.             if (ww[0] != NULL && arg == 0)
  1012.                 {
  1013.                 inbuf = skip_line(inbuf);
  1014.                 *outbuf++ = '\n';
  1015.                 }
  1016.             if (arg > 0) 
  1017.                 {
  1018.                 if (arg == 1)
  1019.                     {
  1020.                     inbuf += skip_white(inbuf);
  1021.                     inbuf += get_string(inbuf,ww,1);
  1022.                     }
  1023.                 else
  1024.                     {
  1025.                     if (isupper(w[1]))
  1026.                         {
  1027.                         inbuf = skip_line(inbuf);
  1028.                         inbuf += get_multi_line(inbuf,ww);
  1029.                         }
  1030.                     else
  1031.                         {
  1032.                         inbuf += get_arg(inbuf,tmp,0);
  1033.                         inbuf = skip_line(inbuf);
  1034.                         if (tmp[0] == NULL)    N = 1;
  1035.                         else        N = atoi(tmp);
  1036.                         inbuf += get_N_lines(inbuf,ww,N);
  1037.                         }
  1038.                     }
  1039.                 sprintf(tmp2,"{%s}",ww);
  1040.                 outbuf = strapp(outbuf,tmp2);
  1041.                 }
  1042.             }
  1043. /* if none of the above commands matched, it is either
  1044.    an illegal macro or an unknown command */
  1045.         else
  1046.             {
  1047.             len = get_till_space(inbuf,ww);
  1048.             sprintf(tmp,"%s%s",w,ww);
  1049.             if (mydef_count > 0 && (i=is_mydef(tmp)) >= 0)
  1050.                 {
  1051.                 inbuf += len;
  1052.                 if (mydef[i].par > 0)
  1053.                     {
  1054.                     if (de_arg > 0)
  1055.                         mydef[mydef_count].par=mydef[i].par;
  1056.                     else
  1057.                         {
  1058.                         outbuf = end_env(outbuf);
  1059.                         outbuf = strapp(outbuf,"\n");
  1060.                         }
  1061.                     }
  1062.                 outbuf = strapp(outbuf,mydef[i].replace);
  1063.                 for (j=1; j <mydef[i].arg_no; j++)
  1064.                     {
  1065.                     inbuf += get_arg(inbuf,ww,1);
  1066.                     sprintf(tmp,"{%s}",ww);
  1067.                     outbuf = strapp(outbuf,tmp);
  1068.                     }
  1069.                 if (de_arg == 0)    envoke_stat(mydef[i].par);
  1070.                 }
  1071.             else
  1072.                 {
  1073.                 fprintf(stderr,
  1074.                 "I cannot translate troff macro %s\n",w);
  1075.                 inbuf += get_line(inbuf,ww,0);
  1076.                 outbuf = strapp(outbuf,"%");
  1077.                 outbuf = strapp(outbuf,w);
  1078.                 outbuf = strapp(outbuf,ww);
  1079.                 if (*inbuf == NULL)    *outbuf++ = '\n';
  1080.                 }
  1081.             }
  1082.         }
  1083.  
  1084. /* some manuals have commented lines beginning with ''' */
  1085.     else if ((c2 == '\'') && !(mid) && (c1 == '\n' || (first_word)))
  1086.         {
  1087.         if (*inbuf == '\'')
  1088.             {
  1089.             inbuf++;
  1090.             if (*inbuf == '\'')
  1091.                 {
  1092.                 inbuf++;
  1093.                 outbuf = strapp(outbuf,"%");
  1094.                 }
  1095.             else    outbuf = strapp(outbuf,"''");
  1096.             }
  1097.         else    outbuf = strapp(outbuf,"'");
  1098.         }
  1099.  
  1100. /* See if it is one of these symbols */
  1101.  
  1102.     else if (strcmp(w,"#") == 0 || strcmp(w,"&") == 0 ||
  1103.          strcmp(w,"{") == 0 || strcmp(w,"}") == 0 ||
  1104.          strcmp(w,"%") == 0 || strcmp(w,"_") == 0 ||
  1105.          strcmp(w,"~") == 0 || strcmp(w,"^") == 0 )
  1106.         {
  1107.         outbuf = strapp(outbuf,"\\");
  1108.         outbuf = strapp(outbuf,w);
  1109.         if (strcmp(w,"~") == 0 || strcmp(w,"^") == 0)
  1110.             outbuf = strapp(outbuf,"{}");
  1111.         }
  1112.  
  1113.     else if (strcmp(w,">") == 0 || strcmp(w,"<") == 0 || strcmp(w,"|") == 0)
  1114.         {
  1115.         sprintf(tmp,"$%s$",w);
  1116.         outbuf = strapp(outbuf,tmp);
  1117.         }
  1118.  
  1119. /* check for backslash commands */
  1120.  
  1121.     else if (strcmp(w,"\\") == 0)
  1122.         {
  1123.         if (*inbuf == ' ' || *inbuf == '\t' || *inbuf == '\n')
  1124.             {
  1125.             outbuf = strapp(outbuf,"\\");
  1126.             *outbuf++ = *inbuf++;
  1127.             }
  1128.         else if (*inbuf == NULL)    ;
  1129.         else if (*inbuf == '-')
  1130.             {
  1131.             inbuf++;
  1132.             outbuf = strapp(outbuf,"--");
  1133.             }
  1134.         else if (*inbuf == '~' || *inbuf == '^')
  1135.             {
  1136.             inbuf++;
  1137.             outbuf = strapp(outbuf,"\\/");
  1138.             }
  1139.         else if (*inbuf == '0')
  1140.             {
  1141.             inbuf++;
  1142.             outbuf = strapp(outbuf,"\\ ");
  1143.             }
  1144.         else if (*inbuf == 'e')
  1145.             {
  1146.             inbuf++;
  1147.             outbuf = strapp(outbuf,"\\bs ");
  1148.             }
  1149.         else if (*inbuf == '\\')
  1150.             {
  1151.             inbuf++;
  1152.             if (*inbuf == '$' && de_arg > 0)
  1153.                 {
  1154.                 inbuf++;
  1155.                 de_arg++;
  1156.                 *outbuf++ = '#';
  1157.                 }
  1158.             else
  1159.                 outbuf = strapp(outbuf,"\\bs ");
  1160.             }
  1161.         else if (*inbuf == '`' || *inbuf == '\'')
  1162.             ;                /* do nothing */
  1163.         else if (*inbuf == '"')
  1164.             {
  1165.             inbuf++;
  1166.             inbuf += get_line(inbuf,ww,0);
  1167.             outbuf = strapp(outbuf,"%");
  1168.             outbuf = strapp(outbuf,ww);
  1169.             }
  1170.         else if (*inbuf == '|')
  1171.             {
  1172.             inbuf++;
  1173.             outbuf = strapp(outbuf,"\\,");
  1174.             }
  1175.         else if (*inbuf == '&')
  1176.             inbuf++;
  1177.         else if (*inbuf == '(')
  1178.             {
  1179.             c1 = *++inbuf;
  1180.             c2 = *++inbuf;
  1181.             inbuf++;
  1182.             if (c1 == 'e' && c2 == 'm')
  1183.                 outbuf = strapp(outbuf,"---");
  1184.             else if (c1 == 'd' && c2 == 'e')
  1185.                 outbuf = strapp(outbuf,"$^\\circ$");
  1186.             else fprintf(stderr,
  1187.                 "I am not prepared to handle \\(%c%c\n",c1,c2);
  1188.             }
  1189.         else if (*inbuf == 's')
  1190.             inbuf +=3;
  1191.         else if (*inbuf == '*')
  1192.             {
  1193.             c1 = *++inbuf;
  1194.             inbuf++;
  1195.             if (c1 == ':')
  1196.                 outbuf = strapp(outbuf,"\\\"");
  1197.             else if (c1 == 'C')
  1198.                 outbuf = strapp(outbuf,"\\v");
  1199.             else if (c1 == ',')
  1200.                 outbuf = strapp(outbuf,"\\c");
  1201.             else if (c1 != '(')
  1202.                 {
  1203.                 sprintf(tmp,"\\%c",c1);
  1204.                 outbuf = strapp(outbuf,tmp);
  1205.                 }
  1206.             else
  1207.                 {
  1208.                 fprintf(stderr,
  1209.                 "I am not prepared to handle \\*( cases\n");
  1210.                 inbuf += 2;
  1211.                 }
  1212.             if (c1 != '(')
  1213.                 {
  1214.                 c1 = *inbuf++;
  1215.                 sprintf(tmp,"{%c}",c1);
  1216.                 outbuf = strapp(outbuf,tmp);
  1217.                 }
  1218.             }
  1219.         else if (*inbuf == 'f')
  1220.             {
  1221.             c1 = *++inbuf;
  1222.             inbuf++;
  1223.             if (c1 == '1' || c1 == 'R')
  1224.                 {
  1225.                 lastfont = thisfont;
  1226.                 thisfont = 1;
  1227.                 if (*inbuf == ' ' || *inbuf == '\t' ||
  1228.                     *inbuf == '\n' || *inbuf == '\f')
  1229.                     {*outbuf++ = ' ';    inbuf++;}
  1230.                 outbuf = strapp(outbuf,"%\n\\rm ");
  1231.                 }
  1232.             else if (c1 == '2' || c1 == 'I')
  1233.                 {
  1234.                 lastfont = thisfont;
  1235.                 thisfont = 2;
  1236.                 if (*inbuf == ' ' || *inbuf == '\t' ||
  1237.                     *inbuf == '\n' || *inbuf == '\f')
  1238.                     {*outbuf++ = ' ';    inbuf++;}
  1239.                 outbuf = strapp(outbuf,"%\n\\it ");
  1240.                 }
  1241.             else if (c1 == '3' || c1 == 'B')
  1242.                 {
  1243.                 lastfont = thisfont;
  1244.                 thisfont = 3;
  1245.                 if (*inbuf == ' ' || *inbuf == '\t' ||
  1246.                     *inbuf == '\n' || *inbuf == '\f')
  1247.                     {*outbuf++ = ' ';    inbuf++;}
  1248.                 outbuf = strapp(outbuf,"%\n\\bf ");
  1249.                 }
  1250.             else if (c1 == 'P')
  1251.                 {
  1252. /* preserve white space - from Nelson Beebe  */
  1253.                 if (*inbuf == ' ' || *inbuf == '\t' ||
  1254.                     *inbuf == '\n' || *inbuf == '\f')
  1255.                     {*outbuf++ = ' ';    inbuf++;}
  1256.                 switch(lastfont)
  1257.                     {
  1258.                     case 1:
  1259.                         outbuf = strapp(outbuf,"\\rm%\n");
  1260.                         thisfont = 1;
  1261.                         break;
  1262.                     case 2:
  1263.                         outbuf = strapp(outbuf,"\\it%\n");
  1264.                         thisfont = 2;
  1265.                         break;
  1266.                     case 3:
  1267.                         outbuf = strapp(outbuf,"\\bf%\n");
  1268.                         thisfont = 3;
  1269.                         break;
  1270.                     default:
  1271.                         outbuf = strapp(outbuf,"\\rm%\n");
  1272.                         thisfont = 1;
  1273.                         break;
  1274.                     }
  1275.                 }
  1276.             else fprintf(stderr,
  1277.                 "I do not understand \\f%c yet\n",c1);
  1278.             }
  1279.         else
  1280.             {
  1281.             fprintf(stderr,"I am not prepared to handle \\%c\n",*inbuf);
  1282.             inbuf++;
  1283.             }
  1284.         }
  1285.  
  1286. /* if non of the above checks, its a dull word; copy it */
  1287.  
  1288.     else
  1289.         outbuf = strapp(outbuf,w);
  1290.     *outbuf = NULL;    ww[0] = NULL;  tmp[0] = NULL;    tmp2[0] = NULL;
  1291.     if (!no_word)    first_word = 0;
  1292.     }
  1293. /* if file end, close opened environments and delimitters */
  1294. if (rec == 0)
  1295.     {
  1296.     if (IP_stat)    outbuf = strapp(outbuf,"\\end{itemize}\n");
  1297.     if (QP_stat)    outbuf = strapp(outbuf,"\\end{quotation}\n");
  1298.     if (TP_stat)    outbuf = strapp(outbuf,"\\end{TPlist}\n");
  1299.     }
  1300.  
  1301. *outbuf = NULL;
  1302. }
  1303. SHAR_EOF
  1304. fi # end of overwriting check
  1305. if test -f 'subs.c'
  1306. then
  1307.     echo shar: will not over-write existing file "'subs.c'"
  1308. else
  1309. cat << \SHAR_EOF > 'subs.c'
  1310. /* COPYRIGHT (C) 1987 Kamal Al-Yahya */
  1311. /* 
  1312. These subroutines do (in general) small things for the translator.
  1313. They appear in alphabetical order and their names are unique in the
  1314. first six characters.
  1315. */
  1316.  
  1317. #include        "setups.h"
  1318. #include        "simil.h"
  1319. #include        "greek.h"
  1320. #include        "flip.h"
  1321. #include        "forbid.h"
  1322. #include        "maths.h"
  1323. #include        "macros.h"
  1324.  
  1325. extern def_count;
  1326. extern mydef_count;
  1327.  
  1328. /* compile-time counting of elements */
  1329. int GRK_count = (sizeof(GRK_list)/sizeof(GRK_list[0]));
  1330. int sim_count = (sizeof(sim_list)/sizeof(sim_list[0]));
  1331. int flip_count = (sizeof(flip_list)/sizeof(flip_list[0]));
  1332. int forbd_count = (sizeof(forbid)/sizeof(forbid[0]));
  1333. int mathcom_count = (sizeof(math)/sizeof(struct math_equiv));
  1334. int macro_count = (sizeof(macro)/sizeof(struct macro_table));
  1335.  
  1336. char *
  1337. alternate(inbuf,outbuf,w)        /* alternate fonts (manual macro) */
  1338. char *inbuf, *outbuf, *w;
  1339. {
  1340. int f1,f2;
  1341. int which=1;
  1342. char font[MAXWORD], font1[MAXWORD], font2[MAXWORD],
  1343.      ww[MAXWORD], tmp[MAXWORD];
  1344.  
  1345. tmp[0] = NULL;
  1346. f1 = w[1];    f2 = w[2];
  1347. if (f1 == 'R')    strcpy(font1,"\\rm");
  1348. if (f1 == 'I')    strcpy(font1,"\\it");
  1349. if (f1 == 'B')    strcpy(font1,"\\bf");
  1350. if (f2 == 'R')    strcpy(font2,"\\rm");
  1351. if (f2 == 'I')    strcpy(font2,"\\it");
  1352. if (f2 == 'B')    strcpy(font2,"\\bf");
  1353.  
  1354. strcpy(font,font1);
  1355. while (*inbuf != '\n' && *inbuf != NULL)
  1356.     {
  1357.     inbuf += get_arg(inbuf,ww,1);
  1358.     sprintf(tmp,"{%s %s}",font,ww);
  1359.     outbuf = strapp(outbuf,tmp);
  1360.     if (which == 1)
  1361.         {
  1362.         which = 2;
  1363.         strcpy(font,font2);
  1364.         }
  1365.     else
  1366.         {
  1367.         which = 1;
  1368.         strcpy(font,font1);
  1369.         }
  1370.     while (*inbuf == ' ' || *inbuf == '\t')
  1371.         inbuf++;
  1372.     }
  1373.  
  1374. return(outbuf);
  1375. }
  1376.  
  1377. int
  1378. CAP_GREEK(w)            /* check if w is in the GREEK list */
  1379. char *w;
  1380. {
  1381. int i;
  1382.  
  1383. for (i=0; i < GRK_count ; i++)
  1384.     {
  1385.     if (strcmp(GRK_list[i],w) == 0)
  1386.         return(1);
  1387.     }
  1388. return(-1);
  1389. }
  1390.  
  1391. char *
  1392. do_table(inbuf,outbuf,offset)
  1393. char *inbuf, *outbuf;
  1394. int *offset;                /* amount to offset inbuf */
  1395. {
  1396. char w[MAXWORD], ww[MAXWORD], format[MAXWORD], tmp[MAXWORD];
  1397. char *ptr;
  1398. int i,j,len,columns=0;
  1399. int tab = '\t';                /* default tab */
  1400.  
  1401. tmp[0] = NULL;
  1402. ptr = inbuf;                /* remember where we started */
  1403. len = get_line(inbuf,w,0);
  1404. if (w[strlen(w)-1] == ';')        /* options */
  1405.     {
  1406.     inbuf += len;
  1407.     if (strncmp(w,"tab",3) == 0)    /* get the tab charecter */
  1408.         tab = w[4];        /* expect something like tab(&); */
  1409.     inbuf = skip_line(inbuf);
  1410.     }
  1411. while (*inbuf != NULL)            /* get the LAST format line */
  1412.     {
  1413.     len = get_line(inbuf,w,0);
  1414.     if (w[strlen(w)-1] != '.')    break;    /* not a fromat line */
  1415.     inbuf += len;
  1416.     for (i=0, j=0; i<len-1; i++)
  1417.         {
  1418.         if (isspace(w[i]))    continue;
  1419.         columns++;
  1420.         if (w[i] == 'l')    format[j] = 'l';
  1421.         else if (w[i] == 'r')    format[j] = 'r';
  1422.         else            format[j] = 'c';
  1423.         j++;
  1424.         }
  1425.     }
  1426. if (columns == 0)
  1427.     {
  1428.     fprintf(stderr,"Sorry, I cannot do tables without a format line\n\
  1429. Doing plain translation of table, lines will be commented\n\
  1430. You need to fix it yourself\n");
  1431.     while (*inbuf != NULL)
  1432.         {
  1433.         (void) getword(inbuf,w);
  1434.         if (strcmp(w,".TE") ==  0)    {inbuf += 4;    break;}
  1435.         inbuf += get_line(inbuf,w,1);
  1436.         *outbuf++ = '%';
  1437.         outbuf = strapp(outbuf,w);
  1438.         outbuf = strapp(outbuf,"\n");
  1439.         inbuf++;        /* skip the \n */
  1440.         }
  1441.     *offset = inbuf - ptr;
  1442.     return(outbuf);
  1443.     }
  1444. format[j] = NULL;
  1445. sprintf(tmp,"\\par\n\\begin{tabular}{%s}\n",format);
  1446. outbuf = strapp(outbuf,tmp);
  1447.  
  1448. while (*inbuf != NULL)
  1449.     {
  1450.     for (i=0; i<columns-1; i++)
  1451.         {
  1452.         (void) getword(inbuf,w);
  1453.         if (i == 0 && (strcmp(w,"\n") == 0 || strcmp(w,"_") == 0))
  1454.             {inbuf++;    i--;    continue;}
  1455.         if (strcmp(w,".TE") == 0)
  1456.             {
  1457.             inbuf += 4;
  1458.             if (i == 0)
  1459.                 {
  1460.                 outbuf -= 3;    /* take back the \\ and the \n */
  1461.                 *outbuf = NULL;
  1462.                 }
  1463.             outbuf = strapp(outbuf,"\n\\end{tabular}\n\\par\n");
  1464.             *offset = inbuf - ptr;
  1465.             return(outbuf);
  1466.             }
  1467.         inbuf += get_table_entry(inbuf,w,tab);
  1468.         inbuf ++;        /* skip tab */
  1469.         troff_tex(w,ww,0,1);
  1470.         sprintf(tmp,"%s & ",ww);
  1471.         outbuf = strapp(outbuf,tmp);
  1472.         }
  1473.     (void) getword(inbuf,w);
  1474.     if (strcmp(w,".TE") == 0)
  1475.         {
  1476.         fprintf(stderr,"Oops! I goofed. I told I you I am not very good at tables\nI've encountered an unexpected end for the table\n\
  1477. You need to fix it yourself\n");
  1478.         inbuf += 4;
  1479.         outbuf = strapp(outbuf,"\\end{tabular}\n\\par\n");
  1480.         *offset = inbuf - ptr;
  1481.         return(outbuf);
  1482.         }
  1483.     inbuf += get_table_entry(inbuf,w,'\n');
  1484.     inbuf++;        /* skip tab */
  1485.     troff_tex(w,ww,0,1);
  1486.     outbuf = strapp(outbuf,ww);
  1487.     outbuf = strapp(outbuf,"\\\\\n");
  1488.     }
  1489. fprintf(stderr,"Oops! I goofed. I told I you I am not very good at tables\n\
  1490. File ended and I haven't finished the table!\n\
  1491. You need to fix it yourself\n");
  1492. *offset = inbuf - ptr;
  1493. outbuf = strapp(outbuf,"\\end{tabular}\n\\par\n");
  1494. return(outbuf);
  1495. }
  1496.  
  1497. char *
  1498. end_env(outbuf)
  1499. char *outbuf;
  1500. {
  1501. if (IP_stat)
  1502.     {
  1503.     IP_stat = 0;
  1504.     outbuf = strapp(outbuf,"\\end{itemize}");
  1505.     }
  1506. if (QP_stat)
  1507.     {
  1508.     QP_stat = 0;
  1509.     outbuf = strapp(outbuf,"\\end{quotation}");
  1510.     }
  1511. if (TP_stat)
  1512.     {
  1513.     TP_stat = 0;
  1514.     outbuf = strapp(outbuf,"\\end{TPlist}");
  1515.     }
  1516. return(outbuf);
  1517. }
  1518.  
  1519. void
  1520. envoke_stat(par)
  1521. int par;
  1522. {
  1523.  
  1524. switch(par)
  1525.     {
  1526.     case 2:
  1527.         IP_stat = 1;
  1528.         break;
  1529.     case 3:
  1530.         TP_stat = 1;
  1531.         break;
  1532.     case 4:
  1533.         QP_stat = 1;
  1534.         break;
  1535.     default:
  1536.         break;
  1537.     }
  1538. }
  1539.  
  1540. char *
  1541. flip(outbuf,w)            /* do the flipping */
  1542. char *outbuf, *w;
  1543. {
  1544. int lb=0, rb=0;
  1545. char ww[MAXWORD], tmp[MAXWORD];
  1546.  
  1547. ww[0] = NULL;    tmp[0] = NULL;
  1548. outbuf--;
  1549. while (*outbuf == ' ' || *outbuf == '\t' || *outbuf == '\n')
  1550.     outbuf--;
  1551. while (1)
  1552.     {
  1553.     if (*outbuf == '{')
  1554.         {
  1555.         lb++;
  1556.         if (lb > rb)    break;
  1557.         }
  1558.     if (*outbuf == '}')    rb++;
  1559.     if (rb == 0)
  1560.         {
  1561.         if (*outbuf != ' ' && *outbuf != '\t' && *outbuf != '\n'
  1562.             && *outbuf != '$')
  1563.             {
  1564.             outbuf--;
  1565.             continue;
  1566.             }
  1567.         else    break;
  1568.         }
  1569.     outbuf--;
  1570.     if (lb == rb && lb != 0)    break;
  1571.     }
  1572. outbuf++;
  1573. if (*outbuf == '\\')
  1574.     {
  1575.     outbuf++;
  1576.     (void) getword(outbuf,tmp);
  1577.     sprintf(ww,"\\%s",tmp);
  1578.     outbuf--;
  1579.     }
  1580. else if (*outbuf == '{')
  1581.     (void) get_brace_arg(outbuf,ww);
  1582. else
  1583.     (void) getword(outbuf,ww);
  1584. *outbuf = NULL;
  1585. sprintf(tmp,"\\%s %s",w,ww);
  1586. outbuf = strapp(outbuf,tmp);
  1587. return(outbuf);
  1588. }
  1589.  
  1590. char *
  1591. flip_twice(outbuf,w,ww)        /* take care of things like x hat under */
  1592. char *outbuf, *w, *ww;
  1593. {
  1594. int lb=0, rb=0;
  1595. char tmp1[MAXWORD], tmp2[MAXWORD];
  1596.  
  1597. tmp1[0] = NULL;        tmp2[0] = NULL;
  1598. outbuf--;
  1599. while (*outbuf == ' ' || *outbuf == '\t' || *outbuf == '\n')
  1600.     outbuf--;
  1601. while (1)
  1602.     {
  1603.     if (*outbuf == '{')
  1604.         {
  1605.         lb++;
  1606.         if (lb > rb)    break;
  1607.         }
  1608.     if (*outbuf == '}')    rb++;
  1609.     if (rb == 0)
  1610.         {
  1611.         if (*outbuf != ' ' && *outbuf != '\t' && *outbuf != '\n'
  1612.             && *outbuf != '$')
  1613.             {
  1614.             outbuf--;
  1615.             continue;
  1616.             }
  1617.         else    break;
  1618.         }
  1619.     outbuf--;
  1620.     if (lb == rb && lb != 0)    break;
  1621.     }
  1622. outbuf++;
  1623. if (*outbuf == '\\')
  1624.     {
  1625.     outbuf++;
  1626.     (void) getword(outbuf,tmp2);
  1627.     sprintf(tmp1,"\\%s",tmp2);
  1628.     outbuf--;
  1629.     }
  1630. else if (*outbuf == '{')
  1631.     (void) get_brace_arg(outbuf,tmp1);
  1632. else
  1633.     (void) getword(outbuf,tmp1);
  1634. *outbuf = NULL;
  1635. sprintf(tmp2,"\\%s{\\%s %s}",w,ww,tmp1);
  1636. outbuf = strapp(outbuf,tmp2);
  1637. return(outbuf);
  1638. }
  1639.  
  1640. int
  1641. get_arg(inbuf,w,rec)        /* get argumnet */
  1642. char *inbuf, *w;
  1643. int rec;        /* rec=1 means recursive */
  1644. {
  1645. int c,len,i;
  1646. char ww[MAXWORD];
  1647. int delim;
  1648.  
  1649. len=0;
  1650. while ((c = *inbuf) == ' ' || c == '\t')    /* skip spaces and tabs */
  1651.         {inbuf++;    len++;}
  1652. i=0;
  1653. if (*inbuf == '{' || *inbuf == '\"')
  1654.     {
  1655.     if (*inbuf == '{')    delim = '}';
  1656.     else            delim = '\"';
  1657.     inbuf++;    len++;
  1658.     while ((c = *inbuf++) != NULL && c != delim && i < MAXWORD)
  1659.         {
  1660.         if (c == ' ' && delim == '\"')    ww[i++] = '\\';
  1661.         ww[i++] = (char)c;    len++;
  1662.         }
  1663.     len++;
  1664.     }
  1665. else
  1666.     {
  1667.     while ((c = *inbuf++) != NULL && c != ' ' && c != '\t' && c != '\n'
  1668.         && c != '$' && c != '}' && i < MAXWORD)
  1669.         {
  1670.         if (math_mode && c == '~')    break;
  1671.         ww[i++] = (char)c;    len++;
  1672.         }
  1673.     }
  1674. ww[i] = NULL;
  1675. if (rec == 1)                /* check if recursion is rquired */
  1676.     troff_tex(ww,w,1,1);
  1677. else
  1678.     strcpy(w,ww);
  1679. return(len);
  1680. }
  1681.  
  1682. void
  1683. get_brace_arg(buf,w)        /* get argumnet surrounded by braces */
  1684. char *buf, *w;
  1685. {
  1686. int c,i, lb=0, rb=0;
  1687.  
  1688. i=0;
  1689. while ((c = *buf++) != NULL)
  1690.     {
  1691.     w[i++] = (char)c;
  1692.     if (c == '{')    lb++;
  1693.     if (c == '}')    rb++;
  1694.     if (lb == rb)    break;
  1695.     }
  1696. w[i] = NULL;
  1697. }
  1698.  
  1699. int
  1700. get_defword(inbuf,w,illegal)        /* get "define" or .de word */
  1701. char *inbuf, *w;            /* delimited by space only */
  1702. int *illegal;
  1703. {
  1704. int c,i;
  1705.  
  1706. *illegal = 0;
  1707. for (i=0; (c = *inbuf++) != NULL && c != ' ' && c != '\n'
  1708.         && c != '\t' && i < MAXWORD; i++)
  1709.     {
  1710.     w[i] = (char)c;
  1711.     if (isalpha(c) == 0)    *illegal = 1;    /* illegal TeX macro */ 
  1712.     }
  1713. w[i] = NULL;
  1714. if (*illegal == 0)
  1715.     if (is_forbid(w) >= 0)        *illegal=1;
  1716. return(i);
  1717. }
  1718.  
  1719. int
  1720. get_line(inbuf,w,rec)        /* get the rest of the line */
  1721. char *inbuf, *w;
  1722. int rec;            /* rec=1 means recursion is required */
  1723. {
  1724. int c,i,len;
  1725. char ww[MAXLINE];
  1726.  
  1727. i=0;    len=0;
  1728. while ((c = *inbuf++) != NULL && c != '\n' && len < MAXLINE)
  1729.         {ww[i++] = (char)c;    len++;}
  1730. ww[i] = NULL;
  1731. if (rec == 1)
  1732.     troff_tex(ww,w,0,1);
  1733. else
  1734.     strcpy(w,ww);
  1735. return(len);
  1736. }
  1737.  
  1738. int
  1739. get_multi_line(inbuf,w)        /* get multi-line argument */
  1740. char *inbuf, *w;
  1741. {
  1742. int len=0,l=0,lines=0;
  1743. char tmp[MAXWORD];
  1744. int c1,c2;
  1745.  
  1746. w[0] = NULL;    tmp[0] = NULL;
  1747. while (*inbuf != NULL)
  1748.     {
  1749.     c1 = *inbuf;    c2 = *++inbuf;        --inbuf;
  1750.     if (c1 == '.' && isupper(c2))        break; 
  1751.     lines++;
  1752.     if (lines > 1)
  1753.         strcat(w," \\\\\n");
  1754.     l = get_line(inbuf,tmp,1);
  1755.     strcat(w,tmp);
  1756.     len += l+1;    inbuf += l+1;
  1757.     }
  1758. len--;        inbuf--;
  1759. return(len);
  1760. }
  1761.  
  1762. int
  1763. get_mydef(inbuf,w)        /* get the macro substitution */
  1764. char *inbuf, *w;
  1765. {
  1766. int c1,c2,l,len;
  1767. char tmp[MAXWORD];
  1768.  
  1769. tmp[0] = NULL;
  1770. len=1;
  1771. while (*inbuf != NULL)
  1772.     {
  1773.     c1 = *inbuf;    c2 = *++inbuf;        --inbuf;
  1774.     if (c1 == '.' && c2 == '.')        break; 
  1775.     l = get_line(inbuf,tmp,1);
  1776.     strcat(w,tmp);
  1777.     len += l+1;    inbuf += l+1;
  1778.     }
  1779. return(len);
  1780. }
  1781. int
  1782. get_N_lines(inbuf,w,N)        /* get N lines */
  1783. char *inbuf, *w;
  1784. int N;
  1785. {
  1786. int len=0,l=0,lines=0;
  1787. char tmp[MAXWORD];
  1788.  
  1789. w[0] = NULL;    tmp[0] = NULL;
  1790. while (*inbuf != NULL && lines < N)
  1791.     {
  1792.     lines++;
  1793.     if (lines > 1)
  1794.         strcat(w," \\\\\n");
  1795.     l = get_line(inbuf,tmp,1);
  1796.     strcat(w,tmp);
  1797.     len += l+1;    inbuf += l+1;
  1798.     }
  1799. len--;        inbuf--;
  1800. return(len);
  1801. }
  1802.  
  1803. int
  1804. get_no_math(inbuf,w)        /* get text surrounded by quotes in math mode */
  1805. char *inbuf, *w;
  1806. {
  1807. int c,i,len;
  1808.  
  1809. len = 0;
  1810. for (i=0; (c = *inbuf++) != NULL && c != '\"' && i < MAXWORD; i++)
  1811.     {
  1812.     if (c == '{' || c == '}')
  1813.         {w[i] = '\\';    w[++i] = (char)c;}
  1814.     else
  1815.         w[i] = (char)c;
  1816.     len++;
  1817.     }
  1818. w[i] = NULL;
  1819. return(len);
  1820. }
  1821.  
  1822. char *
  1823. get_over_arg(inbuf,ww)        /* get the denominator of over */
  1824. char *inbuf, *ww;
  1825. {
  1826. char w[MAXWORD], tmp1[MAXWORD], tmp2[MAXWORD];
  1827. int len;
  1828.  
  1829. w[0] = NULL;    tmp1[0] = NULL;        tmp2[0] = NULL;
  1830. inbuf += getword(inbuf,tmp1);        /* read first word */
  1831. inbuf += skip_white(inbuf);
  1832. len = getword(inbuf,tmp2);        /* read second word */
  1833. strcat(w,tmp1);    strcat(w," ");
  1834.  
  1835. /* as long as there is a sup or sub read the next two words */
  1836. while (strcmp(tmp2,"sub") == 0 || strcmp(tmp2,"sup") == 0)
  1837.     {
  1838.     inbuf += len;
  1839.     strcat(w,tmp2); strcat(w," ");
  1840.     inbuf += skip_white(inbuf);
  1841.     inbuf += getword(inbuf,tmp1);
  1842.     strcat(w,tmp1); strcat(w," ");
  1843.     inbuf += skip_white(inbuf);
  1844.     len = getword(inbuf,tmp2);
  1845.     }
  1846. troff_tex(w,ww,0,1);
  1847. return(inbuf);
  1848. }
  1849.  
  1850. int
  1851. get_ref(inbuf,w)        /* get reference */
  1852. char *inbuf, *w;
  1853. {
  1854. int len=0, l=0, lines=0;
  1855. char tmp[MAXWORD];
  1856.  
  1857. w[0] = NULL;    tmp[0] = NULL;
  1858. while (*inbuf != NULL)
  1859.     {
  1860.     if (*inbuf == '\n')        break;
  1861.     (void) getword(inbuf,tmp);
  1862.     if (tmp[0] == '.' && isupper(tmp[1]))
  1863.         {
  1864. /* these commands don't cause a break in reference */
  1865.         if (strcmp(tmp,".R") != 0 && strcmp(tmp,".I") != 0
  1866.             && strcmp(tmp,".B") != 0)
  1867.             break; 
  1868.         }
  1869.     else if (tmp[0] == '.' && !(isupper(tmp[1])))
  1870.         {
  1871. /* these commands don't cause a break in reference */
  1872.         if (strcmp(tmp,".br") != 0 && strcmp(tmp,".bp") != 0)
  1873.             break; 
  1874.         }
  1875.     l = get_line(inbuf,tmp,1);
  1876.     lines++;
  1877.     if (lines > 1)        strcat(w," ");
  1878.     strcat(w,tmp);
  1879.     len += l+1;    inbuf += l+1;
  1880.     }
  1881. len--;        inbuf--;
  1882. return(len);
  1883. }
  1884.  
  1885. void
  1886. get_size(ww,PARAMETER)
  1887. char *ww;
  1888. struct measure *PARAMETER;
  1889. {
  1890. int sign=0, units=0;
  1891. float value;
  1892.  
  1893. if (ww[0] == NULL)
  1894.     {
  1895.     if (PARAMETER->def_value == 0)
  1896.         {
  1897.         PARAMETER->value = PARAMETER->old_value;
  1898.         strcpy(PARAMETER->units,PARAMETER->old_units);
  1899.         }
  1900.     else
  1901.         {
  1902.         PARAMETER->value = PARAMETER->def_value;
  1903.         strcpy(PARAMETER->units,PARAMETER->def_units);
  1904.         }
  1905.     }
  1906. else
  1907.     {
  1908.     PARAMETER->old_value = PARAMETER->value;
  1909.     strcpy(PARAMETER->old_units,PARAMETER->units);
  1910.     parse_units(ww,&sign,&value,&units);
  1911.     if (units == 'p')
  1912.         strcpy(PARAMETER->units,"pt");
  1913.     else if (units == 'i')
  1914.         strcpy(PARAMETER->units,"in");
  1915.     else if (units == 'c')
  1916.         strcpy(PARAMETER->units,"cm");
  1917.     else if (units == 'm')
  1918.         strcpy(PARAMETER->units,"em");
  1919.     else if (units == 'n')
  1920.         {
  1921.         value = .5*value;    /* n is about half the width of m */
  1922.         strcpy(PARAMETER->units,"em");
  1923.         }
  1924.     else if (units == 'v')
  1925.         strcpy(PARAMETER->units,"ex");
  1926.     else if (units == 0)
  1927.         {
  1928.         if (sign == 0 || PARAMETER->old_units[0] == NULL)
  1929.             strcpy(PARAMETER->units,PARAMETER->def_units);
  1930.         else
  1931.             strcpy(PARAMETER->units,PARAMETER->old_units);
  1932.         }
  1933.     else
  1934.         {
  1935.         fprintf(stderr,"unknown units %c, using default units\n");
  1936.         strcpy(PARAMETER->units,PARAMETER->def_units);
  1937.         }
  1938.     if (sign == 0)    PARAMETER->value = value;
  1939.     else        PARAMETER->value = PARAMETER->old_value + sign*value;
  1940.     }
  1941. }
  1942.  
  1943. int
  1944. get_string(inbuf,w,rec)        /* get the rest of the line -- Nelson Beebe */
  1945. char *inbuf, *w;
  1946. int rec;            /* rec=1 means recursion is required */
  1947. {
  1948. register int c,i,len;
  1949. char ww[MAXLINE];
  1950. register char *start;
  1951.  
  1952. if (*inbuf != '\"')
  1953.     return(get_line(inbuf,w,rec));
  1954. start = inbuf;                /* remember start so we can find len */
  1955. i=0;
  1956. inbuf++;                /* point past initial quote */
  1957. while ((c = *inbuf++) != NULL && c != '\"' && c != '\n' && i < MAXLINE)
  1958.     ww[i++] = (char)c;
  1959. ww[i] = NULL;
  1960. if (c != '\n')                /* flush remainder of line */
  1961.     while ((c = *inbuf++) != '\n')
  1962.     /* NO-OP */;
  1963. len = inbuf - start - 1;        /* count only up to NL, not past */
  1964. if (rec == 1)
  1965.     troff_tex(ww,w,0,1);
  1966. else
  1967.     strcpy(w,ww);
  1968. return(len);
  1969. }
  1970.  
  1971. int
  1972. get_sub_arg(inbuf,w)        /* get the argument for sub and sup */
  1973. char *inbuf, *w;
  1974. {
  1975. int c,len,i;
  1976. char ww[MAXWORD], tmp[MAXWORD];
  1977.  
  1978. len=0;    tmp[0] = NULL;
  1979. while ((c = *inbuf) == ' ' || c == '\t')
  1980.         {inbuf++;    len++;}
  1981. i=0;
  1982. while ((c = *inbuf++) != NULL && c != ' ' && c != '\t' && c != '\n'
  1983.         && c != '$' && c != '}' && c != '~' && i < MAXWORD)
  1984.         {ww[i++] = (char)c;    len++;}
  1985. ww[i] = NULL;
  1986. if (strcmp(ww,"roman") == 0  || strcmp(ww,"bold") == 0 || strcmp(w,"italic") == 0)
  1987.     {
  1988.     (void) get_arg(inbuf,tmp,0);
  1989.     sprintf(ww,"%s%c%s",ww,c,tmp);
  1990.     len += strlen(tmp)+1;
  1991.     }
  1992. troff_tex(ww,w,0,1);        /* recursive */
  1993. return(len);
  1994. }
  1995.  
  1996. int
  1997. get_table_entry(inbuf,w,tab)
  1998. char *inbuf, *w;
  1999. int tab;
  2000. {
  2001. int c, i=0;
  2002.  
  2003. for (i=0; (c = *inbuf++) != NULL && c != tab && i < MAXWORD; i++)
  2004.         w[i] = (char)c;
  2005. w[i] = NULL;
  2006.  
  2007. return(i);
  2008. }
  2009.  
  2010. int
  2011. get_till_space(inbuf,w)            /* get characters till the next space */
  2012. char *inbuf, *w;
  2013. {
  2014. int c,i;
  2015.  
  2016. for (i=0; (c = *inbuf++) != NULL && c != ' ' && c != '\n'
  2017.         && c != '\t' && i < MAXWORD; i++)
  2018.     w[i] = (char)c;
  2019. w[i] = NULL;
  2020. return(i);
  2021. }
  2022.  
  2023. int
  2024. getdef(inbuf,ww)        /* get the define substitution */
  2025. char *inbuf, *ww;
  2026. {
  2027. int c,i,len;
  2028. int def_delim;
  2029. char w[MAXWORD];
  2030.  
  2031. def_delim = *inbuf++;        /* take first character as delimiter */
  2032. len=1;        i=0;
  2033. while ((c = *inbuf++) != NULL && c != def_delim && i < MAXWORD)
  2034.     {len++;        w[i++] = (char)c;}
  2035. w[i] = NULL;
  2036. len++;
  2037. if (c != def_delim)
  2038.     {
  2039.     fprintf(stderr,"WARNING: missing right delimiter in define, define=%s\n",w);
  2040.     len--;
  2041.     }
  2042. troff_tex(w,ww,0,1);        /* now translate the substitution */
  2043. return(len);
  2044. }
  2045.  
  2046. int
  2047. getword(inbuf,w)        /* get an alphanumeric word (dot also) */
  2048. char *inbuf, *w;
  2049. {
  2050. int c,i;
  2051.  
  2052. for (i=0; (c = *inbuf++) != NULL
  2053.     && (isalpha(c) || isdigit(c) || c == '.') && i < MAXWORD; i++)
  2054.         w[i] = (char)c;
  2055. if (i == 0 && c != NULL)
  2056.     w[i++] = (char)c;
  2057. w[i] = NULL;
  2058. return(i);
  2059. }
  2060.  
  2061. void
  2062. GR_to_Greek(w,ww)            /* change GREEK to Greek */
  2063. char *w, *ww;
  2064. {
  2065. *ww++ = '\\';        *ww++ = *w;
  2066. while(*++w != NULL)
  2067.     *ww++ = tolower(*w);
  2068. *ww = NULL;
  2069. }
  2070.  
  2071. int
  2072. is_def(w)        /* check if w was defined by the user */
  2073. char *w;
  2074. {
  2075. int i;
  2076.  
  2077. for (i=0; i < def_count; i++)
  2078.     {
  2079.     if (strcmp(def[i].def_macro,w) == 0)
  2080.         return(i);
  2081.     }
  2082. return(-1);
  2083. }
  2084.  
  2085. int
  2086. is_flip(w)        /* check if w is in the flip list */
  2087. char *w;
  2088. {
  2089. int i;
  2090.  
  2091. for (i=0; i < flip_count; i++)
  2092.     {
  2093.     if (strcmp(flip_list[i],w) == 0)
  2094.         return(i);
  2095.     }
  2096. return(-1);
  2097. }
  2098.  
  2099. int
  2100. is_forbid(w)        /* check if w is one of those sacred macros */
  2101. char *w;
  2102. {
  2103. int i;
  2104.  
  2105. for (i=0; i < forbd_count; i++)
  2106.     {
  2107.     if (strcmp(forbid[i],w) == 0)
  2108.         return(i);
  2109.     }
  2110. return(-1);
  2111. }
  2112.  
  2113. int
  2114. is_mathcom(w,ww)    /* check if w has a simple correspondence in TeX */
  2115. char *w,*ww;
  2116. {
  2117. int i;
  2118.  
  2119. for (i=0; i < mathcom_count; i++)
  2120.     {
  2121.     if (strcmp(math[i].troff_symb,w) == 0)
  2122.         {
  2123.         strcpy(ww,math[i].tex_symb);
  2124.         return(i);
  2125.         }
  2126.     }
  2127. return(-1);
  2128. }
  2129.  
  2130. int
  2131. is_mydef(w)        /* check if w is user-defined macro */
  2132. char *w;
  2133. {
  2134. int i;
  2135.  
  2136. for (i=0; i < mydef_count; i++)
  2137.     {
  2138.     if (strcmp(mydef[i].def_macro,w) == 0)
  2139.         return(i);
  2140.     }
  2141. return(-1);
  2142. }
  2143.  
  2144. int
  2145. is_troff_mac(w,ww,arg,par)/* check if w is a macro or plain troff command */
  2146. char *w,*ww;
  2147. int *arg,*par;
  2148. {
  2149. int i;
  2150.  
  2151. for (i=0; i < macro_count; i++)
  2152.     {
  2153.     if (strcmp(macro[i].troff_mac,w) == 0)
  2154.         {
  2155.         strcpy(ww,macro[i].tex_mac);
  2156.         *arg = macro[i].arg;
  2157.         *par = macro[i].macpar;
  2158.         return(i);
  2159.         }
  2160.     }
  2161. return(-1);
  2162. }
  2163.  
  2164. void
  2165. parse_units(ww,sign,value,units)
  2166. char *ww;
  2167. int *sign, *units;
  2168. float *value;
  2169. {
  2170. int len, k=0, i;
  2171. char tmp[MAXWORD];
  2172.  
  2173. len = strlen(ww);
  2174. if (ww[0] == '-')    *sign = -1;
  2175. else if (ww[0] == '+')    *sign = 1;
  2176. if (*sign != 0)        k++;
  2177.  
  2178. i=0;
  2179. while (k < len)
  2180.     {
  2181.     if (isdigit(ww[k]) || ww[k] == '.')
  2182.         tmp[i++] = ww[k++];
  2183.     else    break;
  2184.     }
  2185. tmp[i] = NULL;
  2186. sscanf(tmp,"%f",value);
  2187. i=0;
  2188. if (k < len)
  2189.     {
  2190.     *units = ww[k++];
  2191.     if (k < len)
  2192.         fprintf(stderr,
  2193.         "Suspect problem in parsing %s, unit used is %c\n",ww,*units);
  2194.     }
  2195. }
  2196.  
  2197. void
  2198. scrbuf(in,out)            /* copy input to output */
  2199. FILE *in,*out;
  2200. {
  2201. int c;
  2202. while ((c =getc(in)) != EOF)    putc(c,out);
  2203. }
  2204.  
  2205. int
  2206. similar(w)            /* check if w is in the similar list */
  2207. char *w;
  2208. {
  2209. int i;
  2210.  
  2211. for (i=0; i < sim_count ; i++)
  2212.     {
  2213.     if (strcmp(sim_list[i],w) == 0)
  2214.         return(1);
  2215.     }
  2216. return(-1);
  2217. }
  2218.  
  2219. char *
  2220. skip_line(inbuf)        /* ignore the rest of the line */
  2221. char *inbuf;
  2222. {
  2223. while (*inbuf != '\n' && *inbuf != NULL)
  2224.     inbuf++;
  2225. if (*inbuf == NULL)    return(inbuf);
  2226. else            return(++inbuf);
  2227. }
  2228.  
  2229. int
  2230. skip_white(inbuf)        /* skip white space */
  2231. char *inbuf;
  2232. {
  2233. int c,len=0;
  2234.  
  2235. while ((c = *inbuf++) == ' ' || c == '\t' || c == '\n')
  2236.     len++;    
  2237. return(len);
  2238. }
  2239.  
  2240. char *
  2241. strapp(s,tail)  /* copy tail[] to s[], return ptr to terminal NULL in s[] */
  2242. register char *s;    /* Nelson Beebe */
  2243. register char *tail;
  2244. {
  2245. while (*s++ = *tail++)
  2246.     /*NO-OP*/;
  2247. return (s-1);            /* pointer to NULL at end of s[] */
  2248. }
  2249.  
  2250. void
  2251. tmpbuf(in,buffer)
  2252. /* copy input to buffer, buffer holds only MAXLEN characters */
  2253. FILE *in;
  2254. char *buffer;
  2255. {
  2256. int c;
  2257. unsigned int l=0;
  2258.  
  2259. while (l++ < MAXLEN && (c = getc(in)) != EOF)
  2260.     *buffer++ = (char)c;
  2261. if (l >= MAXLEN)
  2262.     {
  2263.     fprintf(stderr,"Sorry: document is too large\n");
  2264.     exit(-1);
  2265.     }
  2266. *buffer = NULL;
  2267. }
  2268. SHAR_EOF
  2269. fi # end of overwriting check
  2270. if test -f 'setups.h'
  2271. then
  2272.     echo shar: will not over-write existing file "'setups.h'"
  2273. else
  2274. cat << \SHAR_EOF > 'setups.h'
  2275. /* setup file */
  2276.  
  2277. #ifndef NO_SGTTY
  2278. #define HAVE_SGTTY 1            /* host has sgtty.h and ioctl.h */
  2279. #endif
  2280.  
  2281. #include        <stdio.h>
  2282. #include        <ctype.h>
  2283. #ifdef MSC
  2284. #include        <string.h>
  2285. #include    <stdlib.h>    /* for type declarations */
  2286. #include    <io.h>        /* for type declarations */
  2287. #else
  2288. #include        <strings.h>
  2289. #endif
  2290.  
  2291. #if HAVE_SGTTY
  2292. #include        <sys/ioctl.h>
  2293. #include        <sgtty.h>
  2294. #endif
  2295.  
  2296. #define    MAXLEN    65535        /* maximum length of document */
  2297. #define    MAXWORD    250        /* maximum word length */
  2298. #define    MAXLINE    500        /* maximum line length */
  2299. #define    MAXDEF    200        /* maximum number of defines */
  2300.  
  2301. extern char *malloc();
  2302. #ifdef IN_TR        /* can only declare globals once */
  2303. #else
  2304. extern
  2305. #endif
  2306. int math_mode,        /* math mode status */
  2307.     de_arg,        /* .de argument */
  2308.     IP_stat,        /* IP status */
  2309.     QP_stat,        /* QP status */
  2310.     TP_stat;        /* TP status */
  2311.  
  2312. #ifdef IN_TR        /* can only declare globals once */
  2313. #else
  2314. extern
  2315. #endif
  2316. struct defs {
  2317.     char *def_macro;
  2318.     char *replace;
  2319.     int illegal;
  2320. } def[MAXDEF];
  2321.  
  2322. #ifdef IN_TR        /* can only declare globals once */
  2323. #else
  2324. extern
  2325. #endif
  2326. struct mydefs {
  2327.     char *def_macro;
  2328.     char *replace;
  2329.     int illegal;
  2330.     int arg_no;
  2331.     int par;        /* if it impiles (or contains) a par break */
  2332. } mydef[MAXDEF];
  2333.  
  2334. #ifdef IN_TR        /* can only declare globals once */
  2335. #else
  2336. extern
  2337. #endif
  2338. struct measure {
  2339.     char old_units[MAXWORD];    float old_value;
  2340.     char units[MAXWORD];        float value;
  2341.     char def_units[MAXWORD];    /* default units */
  2342.     int def_value;            /* default value: 0 means take last one */
  2343. } linespacing, indent, tmpind, space, vspace;
  2344.  
  2345. #ifdef ANSI
  2346. char*    alternate(char*, char*, char*);
  2347. int    CAP_GREEK(char*);
  2348. char*    do_table(char*,char*,int);
  2349. char*    end_env(char*);
  2350. void    envoke_stat(int);
  2351. char*    flip(char*,char*);
  2352. char*    flip_twice(char*,char*,char*);
  2353. int    get_arg(char*,char*,int ,int );
  2354. void    get_brace_arg(char*,char*);
  2355. int    get_defword(char*,char*,int*);
  2356. int    get_line(char*,char*,int );
  2357. int    get_multi_line(char*,char*);
  2358. int    get_mydef(char*,char*);
  2359. int    get_N_lines(char *,char *,int);
  2360. int    get_no_math(char*,char*);
  2361. char*    get_over_arg(char*,char*);
  2362. int    get_ref(char*,char*);
  2363. int    get_string(char*,char*,int );
  2364. void    get_size(char*,char*,char*);
  2365. int    get_sub_arg(char*,char*);
  2366. int    get_till_space(char*,char*);
  2367. int    getdef(char*,char*);
  2368. int    getword(char*,char*);
  2369. void    GR_to_Greek(char*,char*);
  2370. int    is_def(char*);
  2371. int    is_flip(char*);
  2372. int    is_forbid(char*);
  2373. int    is_mathcom(char*,char*);
  2374. int    is_mydef(char *);
  2375. int    is_troff_mac(char*,char*,int*);
  2376. int    main(int ,char **);
  2377. void    parse_units(char*,int,int,int);
  2378. void    scrbuf(FILE*,FILE*);
  2379. int    similar(char*);
  2380. char*    skip_line(char*);
  2381. int    skip_white(char*);
  2382. char*    strapp(char*,char*);
  2383. void    tmpbuf(FILE*,char*);
  2384. void    troff_tex(char *,char *,int );
  2385. #else
  2386. char*    alternate();
  2387. int    CAP_GREEK();
  2388. char*    do_table();
  2389. char*    end_env();
  2390. void    envoke_stat();
  2391. char*    flip();
  2392. char*    flip_twice();
  2393. int    get_arg();
  2394. void    get_brace_arg();
  2395. int    get_defword();
  2396. int    get_line();
  2397. int    get_multi_line();
  2398. int    get_mydef();
  2399. int    get_N_lines();
  2400. int    get_no_math();
  2401. char*    get_over_arg();
  2402. int    get_ref();
  2403. int    get_string();
  2404. void    get_size();
  2405. int    get_till_space();
  2406. int    get_sub_arg();
  2407. int    getdef();
  2408. int    getword();
  2409. void    GR_to_Greek();
  2410. int    is_def();
  2411. int    is_flip();
  2412. int    is_forbid();
  2413. int    is_mathcom();
  2414. int    is_mydef();
  2415. int    is_troff_mac();
  2416. int    main();
  2417. void    parse_units();
  2418. void    scrbuf();
  2419. int    similar();
  2420. char*    skip_line();
  2421. int    skip_white();
  2422. char*    strapp();
  2423. void    tmpbuf();
  2424. void    troff_tex();
  2425. #endif
  2426. SHAR_EOF
  2427. fi # end of overwriting check
  2428. if test -f 'simil.h'
  2429. then
  2430.     echo shar: will not over-write existing file "'simil.h'"
  2431. else
  2432. cat << \SHAR_EOF > 'simil.h'
  2433. /*
  2434. This file contains a list of math words that are similar in the
  2435. two languages (in fact identical except for TeX's backslah).
  2436. If I overlooked anything out, it can be put here
  2437. Do NOT put here words that are similar but require some action (like over)
  2438. */
  2439. char *sim_list[] =
  2440. {
  2441. "alpha",    "approx",    "beta",     "cdot",     "chi",      "cos",
  2442. "cosh",     "cot",       "coth",     "delta",    "epsilon",  "eta",
  2443. "exp",      "gamma",     "int",      "kappa",    "lambda",   "lim",
  2444. "log",      "matrix",    "mu",       "nu",       "omega",    "partial",
  2445. "phi",      "pi",        "prime",    "prod",     "psi",      "rho",
  2446. "sigma",    "sin",       "sinh",     "sqrt",     "sum",      "tan",
  2447. "tanh",     "tau",       "theta",    "times",    "xi",       "zeta"
  2448. };
  2449. SHAR_EOF
  2450. fi # end of overwriting check
  2451. if test -f 'greek.h'
  2452. then
  2453.     echo shar: will not over-write existing file "'greek.h'"
  2454. else
  2455. cat << \SHAR_EOF > 'greek.h'
  2456. /*
  2457. This file contains the list of the upper-case Greek letters.
  2458. In case I overlooked any, it can be added here.
  2459. */
  2460. char *GRK_list[] =
  2461. {
  2462. "ALPHA",    "BETA",    "CHI",    "DELTA",   "EPSILON",
  2463. "ETA",      "GAMMA",   "KAPPA",  "LAMDA",   "MU",
  2464. "NU",       "OMEGA",   "PHI",    "PI",      "PSI",
  2465. "RHO",      "SIGMA",   "TAU",    "THETA",   "XI",    "ZETA"
  2466. };
  2467. SHAR_EOF
  2468. fi # end of overwriting check
  2469. if test -f 'flip.h'
  2470. then
  2471.     echo shar: will not over-write existing file "'flip.h'"
  2472. else
  2473. cat << \SHAR_EOF > 'flip.h'
  2474. /*
  2475. This file contains the words that are placed the opposite way
  2476. in troff and TeX. Is there any more?
  2477. */
  2478. char *flip_list[] =
  2479. {
  2480. "bar",  "dot",   "dotdot",   "hat",    "tilde",   "under",     "vec"
  2481. };
  2482. SHAR_EOF
  2483. fi # end of overwriting check
  2484. if test -f 'forbid.h'
  2485. then
  2486.     echo shar: will not over-write existing file "'forbid.h'"
  2487. else
  2488. cat << \SHAR_EOF > 'forbid.h'
  2489. /*
  2490. This file contains TeX commands that cannot be re-defined.
  2491. Re-defining them is not permitted by TeX (or they may produce
  2492. unpredictable consequences).
  2493. If the troff user happens to re-define one of these, it will be replaced.
  2494. This list is extracted from the starred entries in the index of the TeXBook.
  2495. They are entered here in alphabetical order.
  2496. If the macro has non-alphabetical characters, it will be trapped
  2497. somewhere else; it needn't be put here.
  2498. This list is added to make the program more robust.
  2499. Note that the backslash is omitted.
  2500. */
  2501. char *forbid[] =
  2502. {
  2503. "atop",     "char",    "copy",     "count",    "cr",      "crcr",
  2504. "day",      "def",     "divide",   "dp",       "dump",    "edef",
  2505. "else",     "end",     "eqno",     "fam",      "fi",      "font",
  2506. "gdef",     "global",  "halign",   "hbox",     "hfil",    "hfill",
  2507. "hfuzz",    "hoffset", "hrule",    "hsize",    "hskip",   "hss",
  2508. "ht",       "if",      "ifcase",   "ifcat",    "ifnum",   "ifodd",
  2509. "iftrue",   "ifx",     "indent",   "input",    "insert",  "kern",
  2510. "left",     "leqno",   "let",      "limits",   "long",    "lower",
  2511. "mag",      "mark",    "mkern",    "month",    "mskip",   "multiply",
  2512. "muskip",   "omit",    "or",       "outer",    "output",  "over",
  2513. "overline", "par",     "raise",    "read",     "right",   "show",
  2514. "span",     "special", "string",   "the",      "time",    "toks",
  2515. "topmark",  "topskip", "unkern",   "unskip",   "vbox",    "vfil",
  2516. "vfill",    "vfuzz",   "voffset",  "vrule",    "vsize",   "vskip",
  2517. "vsplit",   "vss",     "vtop",     "wd",       "write",   "xdef"
  2518. };
  2519. SHAR_EOF
  2520. fi # end of overwriting check
  2521. if test -f 'macros.h'
  2522. then
  2523.     echo shar: will not over-write existing file "'macros.h'"
  2524. else
  2525. cat << \SHAR_EOF > 'macros.h'
  2526. /*
  2527. This file contains the list of non-math macros and plain troff macros.
  2528. Do NOT forget to put the dot for the troff macros, and the backslash
  2529. for TeX macros (two backslashes, one for escape).
  2530. The third column in the list is 0 for macros that have no arguments
  2531. and either 1 or 2 for those that do. If it is 1, then only one line
  2532. will be read as an argument. If it is 2, then lines will be read until
  2533. properly terminated. Arguments for ms macros are terminated by an ms macro
  2534. (e.g. .PP). Plain troff macros are terminated after reading the desired number
  2535. of lines specified by the macro (e.g. .ce 5   will centerline 5 lines).
  2536. The fourth column specifies whether the macro implies a paragraph break
  2537. (par > 1) or not (par = 0). This is needed to terminate some environments.
  2538. If .LP, or .PP, par=1; if .IP, par=2; if .TP, par=3; if .QP, par=4.
  2539. */
  2540. struct macro_table {
  2541.     char *troff_mac, *tex_mac;
  2542.     int arg, macpar;
  2543. } macro[] = {
  2544.  
  2545. /*  troff macro        TeX macro           argument    par    */
  2546.     ".1C",         "\\onecolumn",            0,    1,
  2547.     ".2C",         "\\twocolumn",            0,    1,
  2548.     ".AE",         "\\end{abstract}",        0,    1,
  2549.     ".AI",         "\\authoraff",            2,    1,
  2550.     ".AU",         "\\author",            2,    1,
  2551.     ".Ac",         "\\ACK",              0,    1,
  2552.     ".B1",         "\\boxit{",            0,    0,
  2553.     ".B2",         "}",                0,    0,
  2554.     ".DE",         "\\displayend",        0,    1,
  2555.     ".DS",         "\\displaybegin",        0,    1,
  2556.     ".FE",         "}",                0,    0,
  2557.     ".FS",         "\\footnote{",            0,    0,
  2558.     ".Ic",         "\\caption{",            0,    1,
  2559.     ".Ie",         "}\\end{figure}",        0,    1,
  2560.     ".Is",         "\\begin{figure}",        0,    1,
  2561.     ".KS",         "{\\nobreak",            0,    0,
  2562.     ".LP",         "\\par\\noindent",        0,    1,
  2563.     ".MH",         "\\mhead",            2,    1,
  2564.     ".NH",         "\\section",            1,    1,
  2565.     ".PP",         "\\par",            0,    1,
  2566.     ".QE",         "\\end{quotation}",        0,    1,
  2567.     ".QS",         "\\begin{quotation}",        0,    1,
  2568.     ".SH",         "\\shead",            1,    1,
  2569.     ".TH",         "\\phead",            1,    0,
  2570.     ".TL",         "\\title",            2,    1,
  2571.     ".UC",         "",                0,    0,
  2572.     ".UL",         "\\undertext",            1,    0,
  2573.     ".bp",         "\\newpage",            0,    1,
  2574.     ".br",         "\\nwl",            0,    0,
  2575.     ".ce",         "\\cntr",            2,    0,
  2576.     ".cu",         "\\undertext",            2,    0,
  2577.     ".fi",         "\\fill",            0,    0,
  2578.     ".na",         "\\raggedright",        0,    0,
  2579.     ".nf",         "\\nofill",            0,    0,
  2580.     ".ns",         "",                0,    0,
  2581.     ".ul",         "\\undertext",            2,    0
  2582. };
  2583. SHAR_EOF
  2584. fi # end of overwriting check
  2585. if test -f 'maths.h'
  2586. then
  2587.     echo shar: will not over-write existing file "'maths.h'"
  2588. else
  2589. cat << \SHAR_EOF > 'maths.h'
  2590. /*
  2591. This file contains a list of the words that have simple
  2592. correspondence in the two languages.
  2593. Do not put here words that require action (like sub).
  2594. If the word is identical in the two languages (except for TeX's backslash),
  2595. put it in simil.h
  2596. */
  2597.  
  2598. struct math_equiv {
  2599.     char *troff_symb, *tex_symb;
  2600. } math[] = {
  2601. /*    troff name        TeX name        */
  2602.  
  2603.     "~",            "\\ ",
  2604.     "^",            "\\,",
  2605.     "above",        "\\cr",
  2606.     "ccol",            "\\matrix",
  2607.     "cpile",        "\\matrix",
  2608.     "fat",            "",
  2609.     "grad",            "\\nabla",
  2610.     "half",            "{1\\over 2}",
  2611.     "inf",            "\\infty",
  2612.     "inter",        "\\cap",
  2613.     "lcol",            "\\matrix",
  2614.     "lineup",        "",
  2615.     "lpile",        "\\matrix",
  2616.     "mark",            "",
  2617.     "nothing",        "",
  2618.     "pile",            "\\matrix",
  2619.     "rcol",            "\\matrix",
  2620.     "rpile",        "\\matrix",
  2621.     "union",        "\\cup"
  2622. };
  2623. SHAR_EOF
  2624. fi # end of overwriting check
  2625. if test -f 'makefile'
  2626. then
  2627.     echo shar: will not over-write existing file "'makefile'"
  2628. else
  2629. cat << \SHAR_EOF > 'makefile'
  2630. # Use makefile.msc if you are compiling with MS-DOS
  2631.  
  2632. # add -Dtops20 to CFLAGS if you're running it under tops20
  2633. # and add -DANSI if you're using ANSI C
  2634. CFLAGS =
  2635. LINTFLAGS = -abchnpux
  2636. CFILES = tr2tex.c tr.c subs.c
  2637. HFILES = setups.h simil.h greek.h macros.h maths.h flip.h forbid.h
  2638. B =
  2639.  
  2640. default: tr2tex
  2641.  
  2642. tr2tex: tr2tex.o tr.o subs.o
  2643.     cc $(CFLAGS) tr2tex.o tr.o subs.o -o $(B)tr2tex
  2644.  
  2645. tr2tex.o: tr2tex.c setups.h
  2646.     cc $(CFLAGS) -c tr2tex.c
  2647. tr.o: tr.c setups.h
  2648.     cc $(CFLAGS) -c tr.c
  2649. subs.o: subs.c $(HFILES)
  2650.     cc $(CFLAGS) -c subs.c
  2651.  
  2652. lint:
  2653.     lint $(LINTFLAGS) $(CFILES) > lint.lst
  2654.  
  2655. clean:
  2656.     \rm -f *.o core *junk* tr2tex lint.lst
  2657.  
  2658. SHAR_EOF
  2659. fi # end of overwriting check
  2660. if test -f 'makefile.msc'
  2661. then
  2662.     echo shar: will not over-write existing file "'makefile.msc'"
  2663. else
  2664. cat << \SHAR_EOF > 'makefile.msc'
  2665. #-----------------------------------------------------------------------
  2666. # Makefile for troff-to-TeX translator using MS-DOS
  2667. # Make targets:
  2668. #    (none)    same as tr2tex
  2669. #    tr2tex    build translator
  2670. #    lint    run lint on sources
  2671. #    clean    remove object and executable files
  2672. #    share    make ../ttr.sh for mailing
  2673. #
  2674. # Author: Nelson H.F. Beebe     25-Oct-86
  2675.  
  2676. CFLAGS = -O -DMSC -DNO_SGTTY
  2677. CFILES = tr2tex.c tr.c subs.c
  2678. LINTFLAGS = -abchnpux
  2679. B =
  2680.  
  2681. tr2tex:    tr2tex.o tr.o subs.o
  2682.     cc $(CFLAGS) tr2tex.o tr.o subs.o -o $(B)tr2tex
  2683.  
  2684. share:
  2685.     make clean
  2686.     makescript ../ttr.sh *
  2687.  
  2688. tr2tex.o:    tr2tex.c setups.h
  2689.     cc $(CFLAGS) -c tr2tex.c
  2690.  
  2691. tr.o:    tr.c setups.h
  2692.     cc $(CFLAGS) -c tr.c
  2693.  
  2694. subs.o:    subs.c setups.h similar.h greek.h flip.h troff_mac.h mathcom.h
  2695.     cc $(CFLAGS) -c subs.c
  2696.  
  2697. lint:
  2698.     lint $(LINTFLAGS) $(CFILES) > lint.lst
  2699.  
  2700. clean:
  2701.     \rm -f *.o core *junk* tr2tex lint.lst
  2702. SHAR_EOF
  2703. fi # end of overwriting check
  2704. if test -f 'troffms.sty'
  2705. then
  2706.     echo shar: will not over-write existing file "'troffms.sty'"
  2707. else
  2708. cat << \SHAR_EOF > 'troffms.sty'
  2709. % You need these macros since they are refered to by the translator.
  2710. % You can modify them if you want.
  2711. % I would very much want better macros for the headers and footers.
  2712. % Please pass your suggestions to me.        -Kamal
  2713.  
  2714. \def\ps@sepone{%
  2715. \def\@oddhead{}
  2716. \def\@evenhead{}
  2717. \def\@oddfoot{\hfil\it\sepfoot\hfil}
  2718. \def\@evenfoot{\hfil\it\sepfoot\hfil}}
  2719. \def\ps@sep{%
  2720. \def\@oddhead{\hbox{}\it\seprhead\hfil\it\seplhead}
  2721. \def\@evenhead{\it\seprhead\hfil\it\seplhead\hbox{}}
  2722. \def\@oddfoot{\hfil\it\sepfoot\hfil}
  2723. \def\@evenfoot{\hfil\it\sepfoot\hfil}}
  2724. \pagestyle{sep}
  2725. \def\righthead#1{\def\seplhead{#1}}
  2726. \def\lefthead#1{\def\seprhead{#1}}
  2727. \def\footer#1{\def\sepfoot{#1}}
  2728. \footer{}
  2729. \lefthead{}
  2730. \righthead{}
  2731. \thispagestyle{sepone}
  2732. \def\makefootline{\baselineskip24\p@\line{\the\footline}}
  2733. \def\makeheadline{\vbox to 0pt{\vskip-22.5pt \line{vbox to 8.5pt{}\the\headline}\vss}\nointerlineskip}
  2734.  
  2735. \newfont{\bigbf}{ambx10 scaled\magstep 3}
  2736. \newfont{\bigit}{amti10 scaled\magstep 2}
  2737. \newfont{\bigrm}{amr10 scaled\magstep 2}
  2738.  
  2739. \textheight=9in
  2740. \textwidth=6.4in
  2741. \textfloatsep 30pt plus 3pt minus 6pt
  2742. \parskip=5pt
  2743. \oddsidemargin=-.2in
  2744. \voffset=-.1in
  2745. \newdimen\singlespacing
  2746. \singlespacing=11pt     % single line spacing
  2747. \normalbaselineskip=15pt     % 1.5 line spacing
  2748. \baselineskip=\normalbaselineskip
  2749.  
  2750. % multi-line title
  2751. \newenvironment{SEPtitle}{\begin{center}\bigbf}{\end{center}}
  2752. \def\title#1{
  2753.     \begin{SEPtitle}
  2754.     \vbox{\baselineskip=1.5\normalbaselineskip
  2755.     \vskip1in #1\vskip.3in}
  2756.     \end{SEPtitle}}
  2757. % multi-line author
  2758. \newenvironment{SEPauthor}{\begin{center}\bigit}{\end{center}}
  2759. \def\author#1{
  2760.     \begin{SEPauthor}
  2761.     \vbox{#1 \vskip.3cm}
  2762.     \end{SEPauthor}}
  2763. \newenvironment{SEPauthoraff}{\begin{center}\bigrm}{\end{center}}
  2764. \def\authoraff#1{
  2765.     \begin{SEPauthoraff}
  2766.     \vbox{#1 \vskip.2in}
  2767.     \end{SEPauthoraff}}
  2768. % multi-line centered section heading
  2769. \newenvironment{SEPmhead}{\begin{center}\bf}{\end{center}}
  2770. \def\mhead#1{\pagebreak[3]
  2771.     \begin{SEPmhead}\pagebreak[3]
  2772.     \vbox{\vskip.3in #1}\nopagebreak
  2773.     \end{SEPmhead}\nopagebreak}
  2774. % multi-line left-justified subheading
  2775. \newenvironment{SEPshead}{\begin{flushleft}\bf}{\end{flushleft}}
  2776. \def\shead#1{\pagebreak[3]
  2777.     \begin{SEPshead}\pagebreak[3]
  2778.     \vbox{\vskip.2in #1}\nopagebreak
  2779.     \end{SEPshead}\nopagebreak}
  2780.  
  2781. % define ABSTRACT, INTRODUCTION, DISCUSSION, CONCLUSIONS, REFERENCES,
  2782. % and APPENDIX as the first three letters
  2783. \def\ABS{\mhead{ABSTRACT}}
  2784. \def\INT{\mhead{INTRODUCTION}}
  2785. \def\DIS{\mhead{DISCUSSION}}
  2786. \def\CON{\mhead{CONCLUSIONS}}
  2787. \def\ACK{\mhead{ACKNOWLEDGMENT}}
  2788. \def\REF{\mhead{REFERENCES}}
  2789. \def\APP{\mhead{APPENDIX}}
  2790.  
  2791. % reference macro, second ... lines are indented
  2792. \newdimen\dtmp     % temporary dimension variable
  2793. \def\reference#1{ \baselineskip=\singlespacing \dtmp=\hsize
  2794.         \advance\dtmp by-\parindent \parshape 2 0in \hsize \parindent
  2795.         \dtmp \noindent #1 \endgraf \baselineskip=\normalbaselineskip
  2796.         \vskip4pt
  2797.         }
  2798.  
  2799. \newcommand{\bs}{$\backslash$}
  2800. \def\under{\underline}
  2801. \def\dotdot{\ddot}
  2802. \def\nwl{\hfill\break}        % similar to latex's \newline but does not
  2803.                 % complain if there is no line to break
  2804. \def\ind#1{\par\everypar{\hangindent=#1\hangafter=0\hskip-\parindent}}
  2805. \def\tmpind#1{\par\hskip#1}
  2806. \newenvironment{SEPcntr}{\begin{center}}{\end{center}}
  2807. \def\cntr#1{\begin{SEPcntr} #1 \end{SEPcntr}}
  2808. % displayed text, indented, justification off
  2809. \def\displaybegin{\par\begingroup\medskip\narrower\narrower\noindent
  2810.           \obeylines\obeyspaces}
  2811. \def\displayend{\endgroup\smallskip\noindent}
  2812. % fill and nofill
  2813. \def\nofill{\par\begingroup\noindent\obeylines
  2814.     \frenchspacing\@vobeyspaces\linepenalty10000}
  2815. {\catcode`\ =\active\gdef\@vobeyspaces{\catcode`\ \active \let \@xobeysp}}
  2816. \def\@xobeysp{\leavevmode{} }
  2817. \def\fill{\endgroup\noindent}
  2818.  
  2819. % define a boxing macro
  2820. \def\boxit#1{\vbox{\hrule\hbox{\vrule\kern10pt\vbox{\medskip\kern5pt#1\bigskip
  2821. \kern5pt}\kern10pt\vrule}\hrule}}
  2822. SHAR_EOF
  2823. fi # end of overwriting check
  2824. if test -f 'troffman.sty'
  2825. then
  2826.     echo shar: will not over-write existing file "'troffman.sty'"
  2827. else
  2828. cat << \SHAR_EOF > 'troffman.sty'
  2829. % -*-LaTeX-*-
  2830. % <BEEBE.TR2TEX>TROFFMAN.STY.6, 24-Feb-87 09:53:53, Edit by BEEBE
  2831. % These macros are intended to be referenced by a LaTeX
  2832. % \documentstyle[troffman]{article}
  2833. % command.  You can insert an 11pt or 12pt option if you like larger
  2834. % type--sizes set here are computed from the LaTeX point size setting.
  2835. % Size values have been chosen to closely match Unix manual page
  2836. % documents, which are actually too wide and too high for good
  2837. % typographic taste and readability.
  2838. %
  2839. \hbadness=10000                 % do not want underfull box messages--there are
  2840.                                 % usually lots in man pages
  2841. \hfuzz=\maxdimen                % no overfull box messages either
  2842. \voffset=-0.8in                 % man pages start high on page
  2843. \textheight=9in                 % and are long
  2844. \textwidth=6.5in                % troff man pages have very wide text
  2845. \parindent=0pt
  2846. \oddsidemargin=-.2in
  2847. \newdimen\singlespacing
  2848. \singlespacing=10pt                     % LaTeX has (10+\@ptsize)pt
  2849. \addtolength{\singlespacing}{\@ptsize pt} % get size from \documentstyle[??pt]{}
  2850.  
  2851. % Use conventional typesetting baselineskip spacing for 10pt type
  2852. \normalbaselineskip=1.2\singlespacing
  2853. \newlength{\parmargin}  % whole paragraphs indented this much on man pages
  2854. \parmargin=3\normalbaselineskip 
  2855. \baselineskip=\normalbaselineskip
  2856.  
  2857. % page heading/footing
  2858. % NB: we need \hfill, not \hfil, here; otherwise box is filled only to current
  2859. %     paragraph width
  2860. \newcommand{\phead}[3]{%
  2861.    \renewcommand{\@oddhead}{%\@setpar{\hangindent=0pt\hangafter=0\@@par}
  2862.      {\makebox[\textwidth]{#1(#2) \hfill \rm UNIX Programmer's Manual%
  2863.          \hfill #1(#2)}}}%
  2864.    \renewcommand{\@oddfoot}{%\@setpar{\hangindent=0pt\hangafter=0\@@par}
  2865.       {\makebox[\textwidth]{4th Berkeley distribution \hfill #3%
  2866.          \hfill \rm\thepage}}}%
  2867.    \renewcommand{\@evenfoot}{\@oddfoot}%
  2868.    \renewcommand{\@evenhead}{\@oddhead}%
  2869. }
  2870. % multi-line left-justified subheading
  2871. \def\shead#1{
  2872.         \par % force out previous paragraph with its \hangindent values
  2873.         \@setpar{\hangindent=0pt\hangafter=0\@@par}
  2874.         \typeout{[#1]}  % maybe temporary, but nice for progress report
  2875.         \subsubsection*{#1}
  2876.         \@setpar{\hangindent=\parmargin\hangafter=0\@@par}
  2877. }
  2878.  
  2879. \newcommand{\bs}{$\backslash$}
  2880. \def\under{\underline}
  2881. \def\dotdot{\ddot}
  2882. \def\nwl{\hfill\break}          % similar to LaTex's \newline but does not
  2883.                                 % complain if there is no line to break
  2884. \def\ind#1{\par\everypar{\hangindent=#1\hangafter=0\hskip-\parindent}}
  2885. \def\tmpind#1{\par\hskip#1}
  2886. \newenvironment{SEPcntr}{\begin{center}}{\end{center}}
  2887. \def\cntr#1{\begin{SEPcntr} #1 \end{SEPcntr}}
  2888. % displayed text, indented, justification off
  2889. \def\displaybegin{\par\begingroup\medskip\narrower\narrower\noindent
  2890.                   \obeylines\obeyspaces}
  2891. \def\displayend{\endgroup\smallskip\noindent}
  2892. % fill and nofill
  2893. \def\nofill{\par\begingroup\noindent\obeylines
  2894.     \frenchspacing\@vobeyspaces\linepenalty10000}
  2895. {\catcode`\ =\active\gdef\@vobeyspaces{\catcode`\ \active \let \@xobeysp}}
  2896. \def\@xobeysp{\leavevmode{} }
  2897. \def\fill{\endgroup\noindent}
  2898.  
  2899. % define a boxing macro
  2900. \def\boxit#1{\vbox{\hrule\hbox{\vrule\kern10pt\vbox{\medskip\kern5pt#1\bigskip
  2901. \kern5pt}\kern10pt\vrule}\hrule}}
  2902.  
  2903. % try this TPlist environment
  2904. \newcommand{\TPlistlabel}[1]{\mbox{#1}\hfil}
  2905. \newenvironment{TPlist}[1]{
  2906. \begin{list}{}
  2907.     {
  2908.       \let\makelabel\TPlistlabel
  2909.       \settowidth{\labelwidth}{#1mm}
  2910.       \setlength{\leftmargin}{\parmargin}       % all paragraphs have this much
  2911.       \addtolength{\leftmargin}{\labelwidth}    % space for label
  2912.     }
  2913.   }{
  2914. \end{list}}
  2915. SHAR_EOF
  2916. fi # end of overwriting check
  2917. if test -f 'tr2tex.9'
  2918. then
  2919.     echo shar: will not over-write existing file "'tr2tex.9'"
  2920. else
  2921. cat << \SHAR_EOF > 'tr2tex.9'
  2922. .TH TR2TEX 9 "1 January 1987"
  2923. .UC 4
  2924. .SH NAME
  2925. tr2tex \- convert a document from troff to LaTeX
  2926. .SH SYNOPSIS
  2927. .B tr2tex
  2928. [
  2929. .B -m
  2930. ]
  2931. .I filename
  2932. .SH DESCRIPTION
  2933. .B Tr2tex
  2934. converts a document typeset in
  2935. .B troff
  2936. to a
  2937. .B LaTeX
  2938. format.
  2939. It is intended to do the first pass of the conversion. The user
  2940. should then finish up the rest of the conversion and customize the
  2941. converted manuscript to his/her liking.
  2942. It can also serve as a tutor for those who want to convert from
  2943. troff to LaTeX.
  2944. .PP
  2945. Most of the converted document will be in LaTeX
  2946. but some of it may
  2947. be in plain
  2948. .B TeX.
  2949. It will also use some macros in
  2950. .B troffms.sty
  2951. or
  2952. .B troffman.sty
  2953. which are included in the package and must be available to the document
  2954. when processed with LaTeX.
  2955. .PP
  2956. If there is more than one input file, they will all be converted into
  2957. one LaTeX document.
  2958. .PP
  2959. .B Tr2tex
  2960. understands most of the
  2961. .B -ms
  2962. and
  2963. .B -man
  2964. macros and
  2965. .B eqn
  2966. preprocessor symbols. It also understands several plain
  2967. .B troff
  2968. commands. Few
  2969. .B tbl
  2970. preprocessor commands are understood to help convert very simple tables.
  2971. .PP
  2972. When converting manuals, use the
  2973. .B -m
  2974. flag.
  2975. .PP
  2976. If a troff command cannot be converted, the line that contain that
  2977. command will be commented out.
  2978. .PP
  2979. NOTE: if you have
  2980. .B eqn
  2981. symbols, you must have the in-line mathematics delimiter defined by
  2982. .B delim
  2983. in the file you are converting. If it is defined in another
  2984. setup file, that setup file has to be concatenated with the
  2985. file to be converted, otherwise
  2986. .B tr2tex
  2987. will regard the in-line math as ordinary text.
  2988. .SH BUGS
  2989. Many of these bugs are harmless. Most of them cause local errors
  2990. that can be fixed in the converted manuscript.
  2991. .PP
  2992. \- Some macros and macro arguments are not recognized.
  2993. .PP
  2994. \- Commands that are not separated from their argument by a space are
  2995. not properly parsed (e.g .sp3i).
  2996. .PP
  2997. \- When some operators (notably over, sub and sup) are renamed (via define),
  2998. then they are encountered in the text,
  2999. .B tr2tex
  3000. will treat them as
  3001. ordinary macros and will not apply their rules.
  3002. .PP
  3003. \- rpile, lpile and cpile are treated the same as cpile.
  3004. .PP
  3005. \- rcol, lcol are treated the same as ccol.
  3006. .PP
  3007. \- Math-mode size, gsize, fat, and gfont are ignored.
  3008. .PP
  3009. \- lineup and mark are ignored. The rules are so different.
  3010. .PP
  3011. \- Some troff commands are translated to commands that require
  3012. delimiters that have to be explicitly put. Since they are
  3013. sometimes not put in troff, they can create problems.
  3014. Example: .nf not closed by .fi.
  3015. .PP
  3016. \- When local motions are converted to \\raise or \\lower, an \\hbox
  3017. is needed, which has to be put manually after the conversion.
  3018. .PP
  3019. \- 'a sub i sub j' is converted to 'a_i_j' which TeX
  3020. parses as 'a_i{}_j}' with a complaint that it is vague. 'a sub {i sub j}'
  3021. is parsed correctly and converted to 'a_{i_j}'.
  3022. .PP
  3023. \- Line spacing is not changed within a paragraph in TeX
  3024. (which is a bad practice anyway).
  3025. TeX uses the last line spacing in effect in that paragraph.
  3026. .SH TODO
  3027. Access registers via
  3028. .B .nr
  3029. command.
  3030. .SH SEE ALSO
  3031. texmatch(9), trmatch(9).
  3032. .SH AUTHOR
  3033. Kamal Al-Yahya, Stanford University
  3034. SHAR_EOF
  3035. fi # end of overwriting check
  3036. if test -f 'tr2tex.9-tex-orig'
  3037. then
  3038.     echo shar: will not over-write existing file "'tr2tex.9-tex-orig'"
  3039. else
  3040. cat << \SHAR_EOF > 'tr2tex.9-tex-orig'
  3041. % -*-LaTeX-*-
  3042. % Converted automatically from troff to LaTeX by tr2tex on Fri Feb 20 12:05:23 1987
  3043. % tr2tex was written by Kamal Al-Yahya at Stanford University
  3044. % (Kamal%Hanauma@SU-SCORE.ARPA)
  3045.  
  3046.  
  3047. \documentstyle[troffman]{article}
  3048. \begin{document}
  3049. %
  3050. % input file: tr2tex.9
  3051. %
  3052. \phead{TR2TEX}{9}{1\ January\ 1987}
  3053.  
  3054. \shead{NAME}
  3055. tr2tex -- convert a document from troff to LaTeX
  3056. \shead{SYNOPSIS}
  3057. {\bf tr2tex}
  3058. [
  3059. {\bf -m}
  3060. ]
  3061. {\it filename}
  3062. \shead{DESCRIPTION}
  3063. {\bf Tr2tex}
  3064. converts a document typeset in
  3065. {\bf troff}
  3066. to a
  3067. {\bf LaTeX}
  3068. format.
  3069. It is intended to do the first pass of the conversion. The user
  3070. should then finish up the rest of the conversion and customize the
  3071. converted manuscript to his/her liking.
  3072. It can also serve as a tutor for those who want to convert from
  3073. troff to LaTeX.
  3074. \par
  3075. Most of the converted document will be in LaTeX
  3076. but some of it may
  3077. be in plain
  3078. {\bf TeX.}
  3079. It will also use some macros in
  3080. {\bf troffms.sty}
  3081. or
  3082. {\bf troffman.sty}
  3083. which are included in the package and must be available to the document
  3084. when processed with LaTeX.
  3085. \par
  3086. If there is more than one input file, they will all be converted into
  3087. one LaTeX document.
  3088. \par
  3089. {\bf Tr2tex}
  3090. understands most of the
  3091. {\bf -ms}
  3092. and
  3093. {\bf -man}
  3094. macros and
  3095. {\bf eqn}
  3096. preprocessor symbols. It also understands several plain
  3097. {\bf troff}
  3098. commands. Few
  3099. {\bf tbl}
  3100. preprocessor commands are understood to help convert very simple tables.
  3101. \par
  3102. When converting manuals, use the
  3103. {\bf -m}
  3104. flag.
  3105. \par
  3106. If a troff command cannot be converted, the line that contain that
  3107. command will be commented out.
  3108. \par
  3109. NOTE: if you have
  3110. {\bf eqn}
  3111. symbols, you must have the in-line mathematics delimiter defined by
  3112. {\bf delim}
  3113. in the file you are converting. If it is defined in another
  3114. setup file, that setup file has to be concatenated with the
  3115. file to be converted, otherwise
  3116. {\bf tr2tex}
  3117. will regard the in-line math as ordinary text.
  3118. \shead{BUGS}
  3119. Many of these bugs are harmless. Most of them cause local errors
  3120. that can be fixed in the converted manuscript.
  3121. \par
  3122. -- Some macros and macro arguments are not recognized.
  3123. \par
  3124. -- Commands that are not separated from their argument by a space are
  3125. not properly parsed (e.g .sp3i).
  3126. \par
  3127. -- When some operators (notably over, sub and sup) are renamed (via define),
  3128. then they are encountered in the text,
  3129. {\bf tr2tex}
  3130. will treat them as
  3131. ordinary macros and will not apply their rules.
  3132. \par
  3133. -- rpile, lpile and cpile are treated the same as cpile.
  3134. \par
  3135. -- rcol, lcol are treated the same as ccol.
  3136. \par
  3137. -- Math-mode size, gsize, fat, and gfont are ignored.
  3138. \par
  3139. -- lineup and mark are ignored. The rules are so different.
  3140. \par
  3141. -- Some troff commands are translated to commands that require
  3142. delimiters that have to be explicitly put. Since they are
  3143. sometimes not put in troff, they can create problems.
  3144. Example: .nf not closed by .fi.
  3145. \par
  3146. -- When local motions are converted to \bs raise or \bs lower, an \bs hbox
  3147. is needed, which has to be put manually after the conversion.
  3148. \par
  3149. -- 'a sub i sub j' is converted to 'a\_i\_j' which TeX
  3150. parses as 'a\_i\{\}\_j\}' with a complaint that it is vague. 'a sub \{i sub j\}'
  3151. is parsed correctly and converted to 'a\_\{i\_j\}'.
  3152. \par
  3153. -- Line spacing is not changed within a paragraph in TeX
  3154. (which is a bad practice anyway).
  3155. TeX uses the last line spacing in effect in that paragraph.
  3156. \shead{TODO}
  3157. Access registers via
  3158. {\bf .nr}
  3159. command.
  3160. \shead{SEE ALSO}
  3161. texmatch(9), trmatch(9).
  3162. \shead{AUTHOR}
  3163. Kamal Al-Yahya, Stanford University
  3164. \end{document}
  3165. SHAR_EOF
  3166. fi # end of overwriting check
  3167. if test -f 'README'
  3168. then
  3169.     echo shar: will not over-write existing file "'README'"
  3170. else
  3171. cat << \SHAR_EOF > 'README'
  3172. Please read this file before you install the program.
  3173.  
  3174. Troff-to-TeX translator version .93, March 4, 1987.
  3175. Copyright (C) by 1987 Kamal Al-Yahya.
  3176.  
  3177. This directory contains programs that were developed at the
  3178. Stanford Exploration Project, Geophysics Department, by Kamal Al-Yahya.
  3179. Copying them to any other machine is permitted without prior permission
  3180. provided that copyright messages are kept, no profit is made by copying
  3181. the files, and modifications are clearly documented.
  3182.  
  3183. I would very much appreciate any comments or suggestions. My e-net
  3184. address is
  3185.         kamal@hanauma.stanford.edu
  3186. If it doesn't work try
  3187.         kamal%hanauma@score.stanford.edu
  3188.  
  3189.             INSTALLATION INSTRUCTIONS
  3190.  
  3191. In short, type ``make'' and then run it on the document (try the testfile):
  3192.         tr2tex testfile > testfile.tex
  3193.  
  3194. In details:
  3195.  
  3196. - Use makefile.msc if you're running MS-DOS.
  3197. - In the makefile, define the destination of the executable (default is
  3198.   current directory). Also, add the -O flag if you want to (and the
  3199.   optimizer in your machine is not buggy). The -O flag causes long compilation
  3200.   time but experience has shown that it is unnecessary for this package;
  3201.   time saved in running time is extremely small in the computers I used.
  3202. - If the limit on your unsigned int is not 65535, change MAXLEN in
  3203.   setups.h accordingly.
  3204. - In tr2tex.c, change the document type if you want. The default is article.
  3205.   Also, change the style options to suit your taste. The default
  3206.   is [troffms,11pt] if no flag is used and [troffman] if the -m flag is used.
  3207. - Add necessary -D's to CFLAGS if you need them. The program recognizes the
  3208.   following compiler-time definitions:
  3209.        -Dtops20, -DANSI, -DMSC, -DNO_SGTTY
  3210. - type ``make'' to produce the executable, called ``tr2tex''.
  3211. - Modify troffms.sty and troffman.sty to suit your taste but keep the
  3212.   necessary macro definitions as they will be needed when running latex.
  3213.   Make sure the font names exist on your site. Change them if necessary.
  3214. - Move troffms.sty and troffman.sty to your macros directory.
  3215. - Install and read the manual page.
  3216. - Run the translator on ``testfile'' and the manual page as follows
  3217.         tr2tex testfile > testfile.tex
  3218.         tr2tex -m tr2tex.9 > tr2tex.9.tex
  3219.   
  3220.   and compare ``testfile.tex'' with ``testfile.tex-orig'' and
  3221.   ``tr2tex.9.tex'' with ``tr2tex.9-tex-orig''.
  3222.   If they are not identical, you have not installed it properly.
  3223.  
  3224.  
  3225.             USING THE TRANSLATOR
  3226.  
  3227. You can run the program either by
  3228.         tr2tex < file  > file.tex
  3229. or
  3230.         tr2tex file  > file.tex
  3231. You are most likely to get messages on the standard error telling
  3232. you about things it encounters and cannot do.
  3233.  
  3234. Now you have the translated document. Look at it and see if you
  3235. can spot a major error. Run it through latex. If it runs and produces
  3236. the dvi file, then print it. If you get latex error messages modify
  3237. the translated document accordingly and repeat the latex run, and so on.
  3238. I usually get away with one or two iterations.
  3239.  
  3240. SHAR_EOF
  3241. fi # end of overwriting check
  3242. if test -f 'testfile'
  3243. then
  3244.     echo shar: will not over-write existing file "'testfile'"
  3245. else
  3246. cat << \SHAR_EOF > 'testfile'
  3247. .LP
  3248. .EQ
  3249. delim $$
  3250. gsize 11
  3251. define dC "delta C"
  3252. define xx 'x sup x'
  3253. define B 'bold B'
  3254. define (( 'left ('
  3255. define )) 'right )'
  3256. define ov 'over'
  3257. .EN
  3258. .ds CF %
  3259. .ds LH Al-Yahya
  3260. .ds RH troff to TeX translator
  3261. .TL      
  3262. Testing the troff-to-tex translator
  3263. .AU          
  3264. Kamal Al-Yahya
  3265. .AI
  3266. Stanford University
  3267. .AB
  3268. This file demonstrates the use of \fB tr2tex\fR which translates
  3269. documents written in troff to a LaTeX style.
  3270. Examples are given to show what the translator can do.
  3271. .AE
  3272. .PP
  3273. First let's test some equation written for the
  3274. .B eqn
  3275. preprocessor:
  3276. .EQ (1)
  3277. 2 left ( 1 ~+~ sqrt{omega sub i+1 + zeta -{x+1} over {THETA +1} y + 1} right )
  3278. ~~~=~~~ 1
  3279. .EN
  3280. .EQ
  3281. left [
  3282. matrix {
  3283.    ccol { e sub 1 above . above . above e sub i above . above . above e sub N }
  3284. }
  3285. right ] sub n+1 ~~=~~ y + 1
  3286. .EN
  3287. .EQ
  3288. bold X + roman a ~>=~
  3289. a under hat fwd 20 sum from i to N lim from {x -> k} dC
  3290. .EN
  3291. .EQ
  3292. (( "speed" times "time" = "distance travelled" ))
  3293. .EN
  3294. .EQ
  3295. beta tilde i >= zeta dC
  3296. .EN
  3297. .IP
  3298. In-line math like $beta +1$ which is surrounded by math delimiters, as
  3299. defined by
  3300. .I delim
  3301. is also translated.
  3302. .R
  3303. .PP
  3304. Only simple tables are translated. Translation of more complicated tables
  3305. is painful and I won't do it now. Here is an example:
  3306. .TS
  3307. tab(&);
  3308. l rc n.
  3309. name    & type        & color    & value
  3310. $alpha$    & real        & red    & 2.3
  3311. $x$    & imaginary    & green    & -1.2
  3312. $a + 2$    & real        & white    & 0.0
  3313. .TE
  3314. \" this is a commented text
  3315. .PP
  3316. Now we start a figure.
  3317. .Is
  3318. .sp 3i
  3319. .Ic 1
  3320. This is the caption of the figure.
  3321. .Ie
  3322. .PP
  3323. Try some floating objects.
  3324. .br
  3325. .KS
  3326. This text should be kept in one page. i.e. a page break is discouraged here.
  3327. .KE
  3328. .br
  3329. Now a floating text.
  3330. .KF
  3331. This text should be kept in one page even if we had to move it around,
  3332. since it is a
  3333. .I floating
  3334. object. This is a boxed
  3335. .BX word.
  3336. .KE
  3337. .br
  3338. These characters are special in TeX, so they need to be escaped
  3339. in the translation % & # _, while these characters have to be
  3340. printed in math mode < > |. 
  3341. .FS
  3342. This is a footnote
  3343. .FE
  3344. .PP
  3345. .Ac
  3346. Thanks to all of those who contributed by reporting bugs and suggesting
  3347. some improvements. Special thanks go to Nelson Beebe for all of his valuable
  3348. contributions and suggestions. He is responsible for making the translator
  3349. portable to other computers. He also made significant improvements to
  3350. the translation of manuals.
  3351. .Re
  3352. Knuth, D.E., 1984, The TeXBook, Addison-Wesley Publishing Company.
  3353. .Re
  3354. Lamprt, L., 1986, LaTeX: user's guide & reference manual, Addison-Wesley
  3355. Publishing Company.
  3356. .Re
  3357. Lesk, M.E., 1978, Typing documents on the UNIX
  3358. system: using the -ms macros
  3359. with troff and nroff, UNIX programmer's manual, v. 2B, sec. 3.
  3360. .Re
  3361. McGilton, H. and Morgan, R., 1983, Introducing the UNIX system, McGraw-Hill
  3362. Book Company.
  3363. SHAR_EOF
  3364. fi # end of overwriting check
  3365. if test -f 'testfile.tex-orig'
  3366. then
  3367.     echo shar: will not over-write existing file "'testfile.tex-orig'"
  3368. else
  3369. cat << \SHAR_EOF > 'testfile.tex-orig'
  3370. % -*-LaTeX-*-
  3371. % Converted automatically from troff to LaTeX by tr2tex on Tue Mar  3 23:25:31 1987
  3372. % tr2tex was written by Kamal Al-Yahya at Stanford University
  3373. % (Kamal%Hanauma@SU-SCORE.ARPA)
  3374.  
  3375.  
  3376. \documentstyle[troffms,11pt]{article}
  3377. \begin{document}
  3378. %
  3379. % input file: testfile
  3380. %
  3381. \par\noindent
  3382. \def\dC{\delta C}
  3383. \def\xx{x^x}
  3384. \def\B{{\bf B}}
  3385. \def\ov{\over  }
  3386.  
  3387. \footer{\rm\thepage}
  3388. \lefthead{Al-Yahya}
  3389. \righthead{troff to TeX translator}
  3390. \title{Testing the troff-to-tex translator}
  3391. \author{Kamal Al-Yahya}
  3392. \authoraff{Stanford University}
  3393. \begin{abstract}
  3394. This file demonstrates the use of  %
  3395. \bf tr2tex %
  3396. \rm which translates
  3397. documents written in troff to a LaTeX style.
  3398. Examples are given to show what the translator can do.
  3399. \end{abstract}
  3400. \par
  3401. First let's test some equation written for the
  3402. {\bf eqn}
  3403. preprocessor:
  3404. $$
  3405. 2 \left( 1 \ +\  \sqrt{\omega_{i+1} + \zeta -{x+1  \over \Theta +1} y + 1} \right)
  3406. \ \ \ =\ \ \  1
  3407. \eqno (1)$$
  3408. $$
  3409. \left[
  3410. \matrix {
  3411.    \matrix { e_1 \cr . \cr . \cr e_i \cr . \cr . \cr e_N }
  3412. }
  3413. \right]_{n+1} \ \ =\ \  y + 1
  3414. $$
  3415. $$
  3416. {\bf X} + {\rm a} \ \ge\ 
  3417. \under{\hat a} \kern0.20em \sum_i^N \lim_{{x} \to k} \dC
  3418. $$
  3419. $$
  3420. \left( \ \it\hbox{speed} \times \ \it\hbox{time} = \ \it\hbox{distance travelled} \right)
  3421. $$
  3422. $$
  3423. \tilde \beta i \ge \zeta \dC
  3424. $$
  3425. \begin{itemize}
  3426. \item[{}]
  3427. In-line math like $\beta +1$ which is surrounded by math delimiters, as
  3428. defined by
  3429. {\it delim}
  3430. is also translated.
  3431. \rm
  3432. \end{itemize}\par
  3433. Only simple tables are translated. Translation of more complicated tables
  3434. is painful and I won't do it now. Here is an example:
  3435. \par
  3436. \begin{tabular}{lrcc}
  3437. name     &  type         &  color     &  value\\
  3438. $\alpha$     &  real         &  red     &  2.3\\
  3439. $x$     &  imaginary     &  green     &  -1.2\\
  3440. $a + 2$     &  real         &  white     &  0.0
  3441. \end{tabular}
  3442. \par
  3443. % this is a commented text
  3444. \par
  3445. Now we start a figure.
  3446. \begin{figure}
  3447. \par\vspace{3.0in}
  3448. \caption{
  3449. This is the caption of the figure.
  3450. }\end{figure}
  3451. \par
  3452. Try some floating objects.
  3453. \nwl
  3454. {\nobreak
  3455. This text should be kept in one page. i.e. a page break is discouraged here.
  3456. }
  3457. \nwl
  3458. Now a floating text.
  3459. \begin{figure}
  3460. This text should be kept in one page even if we had to move it around,
  3461. since it is a
  3462. {\it floating}
  3463. object. This is a boxed
  3464. \fbox{word.}
  3465. \end{figure}
  3466. \nwl
  3467. These characters are special in TeX, so they need to be escaped
  3468. in the translation \% \& \# \_, while these characters have to be
  3469. printed in math mode $<$ $>$ $|$. 
  3470. \footnote{
  3471. This is a footnote
  3472. }
  3473. \par
  3474. \ACK
  3475. Thanks to all of those who contributed by reporting bugs and suggesting
  3476. some improvements. Special thanks go to Nelson Beebe for all of his valuable
  3477. contributions and suggestions. He is responsible for making the translator
  3478. portable to other computers. He also made significant improvements to
  3479. the translation of manuals.
  3480. \REF
  3481. \reference{Knuth, D.E., 1984, The TeXBook, Addison-Wesley Publishing Company.}
  3482. \reference{Lamprt, L., 1986, LaTeX: user's guide \& reference manual, Addison-Wesley Publishing Company.}
  3483. \reference{Lesk, M.E., 1978, Typing documents on the UNIX system: using the -ms macros with troff and nroff, UNIX programmer's manual, v. 2B, sec. 3.}
  3484. \reference{McGilton, H. and Morgan, R., 1983, Introducing the UNIX system, McGraw-Hill Book Company.}
  3485. \end{document}
  3486. SHAR_EOF
  3487. fi # end of overwriting check
  3488. if test -f 'diffs.tex'
  3489. then
  3490.     echo shar: will not over-write existing file "'diffs.tex'"
  3491. else
  3492. cat << \SHAR_EOF > 'diffs.tex'
  3493. \documentstyle[tr2tex,11pt]{article}
  3494. \begin{document}
  3495. \def\troff{{\it troff}}
  3496. \def\Troff{{\it Troff}}
  3497. \def\ditroff{{\it ditroff}}
  3498. \def\Ditroff{{\it Ditroff}}
  3499.  
  3500. \title{Differences between \TeX\ and troff typesetters}
  3501.  
  3502. Outlined below are the differences between \TeX\ and \troff\/ that
  3503. I know from experience with the two languages most of which
  3504. obtained while writing {\bf tr2tex}.
  3505. Most of them are advantages \TeX\ has over \troff.
  3506.  
  3507. There are actually more than one type of \TeX, the most
  3508. used ones are \LaTeX and plain \TeX\
  3509. \Troff\/ can also be loaded with various macro packages to
  3510. produce variations to plain \troff. Also, \ditroff\/ (device independent \troff)
  3511. is becoming more and more the standard of \troff.
  3512. The following comparison is made mainly between \LaTeX\ and {\bf ms} \troff.
  3513. It will be mentioned if in a particular case \ditroff\/ makes a difference.
  3514.  
  3515. \begin{itemize}
  3516. \item \TeX\ is not system-dependent. \Troff\/ is a Unix tool.
  3517.  
  3518. \item In \Troff, tables and equations are handled by preprocessors
  3519. while in \TeX\ they are simultaneously processed with text.
  3520.  
  3521. \item \Troff\/'s commands have to start at the beginning of the line
  3522. and start with a dot. Equation symbols are recognized when delimited by space.
  3523. All \TeX\ commands, in math or non-math mode, start with a backslash
  3524. and they don't have to be placed at the beginning of the line.
  3525.  
  3526. \item \TeX\ and \LaTeX\ commands are more verbose than \troff\/'s.
  3527. This can be an advantage or disadvantage depending on the user.
  3528.  
  3529. \item \TeX\ processes {\it boxes} such as lines and paragraphs as one unit.
  3530. This means it can distribute {\it badness} over that box.
  3531. For example, when a spacing between two lines needs to be large, because
  3532. a line has large symbols, it will slightly stretch the
  3533. line spacing in other lines to make the large spacing not look
  3534. too bad. This also makes it avoid orphan lines.
  3535.  
  3536. \item The input to \LaTeX\ is a more structured document with scopes. It makes it
  3537. easier to proofread. \Troff\/'s input is less structured.
  3538.  
  3539. \item Some  \TeX\ drivers make it very easy to include prepared
  3540. graphs with the text. Including graphs with \troff\/'s text is more difficult.
  3541.  
  3542. \item Many fonts can be loaded in a \TeX\ document (up to 32); in \troff,
  3543. the limit is 4 (\ditroff\/ does not have this restriction).
  3544.  
  3545. \item Non-math macros are defined just like math macros in \TeX.
  3546. In \troff, {\bf define} is used for math definitions and {\bf .de} is
  3547. used for non-math macros.
  3548. \Troff\/'s macros can be made up from anything while
  3549. \TeX\ macros cannot have non-letters which is a nuisance sometimes.
  3550.  
  3551. \item There is no limit on the page size in \TeX. The size is limited only by
  3552. the output device. \Troff\/'s paper size is limited.
  3553.  
  3554. \item \TeX\ is interactive, while \troff\/ is not. However, not many people can
  3555. benefit from this feature since they have to be skillful in answering
  3556. its questions.
  3557.  
  3558. \item \TeX\ and \LaTeX\ give a {\bf l\,o\,n\,g} ambiguous log file that does not
  3559. exactly tell what the error is. \Troff\/ does not give error messages.
  3560.  
  3561. \item \LaTeX\ automatically numbers equations and figures, etc. A powerful
  3562. cross-referencing technique relieves the user from worrying about having
  3563. the right sequence of equations' and figures' numbers. This feature
  3564. is not available in \troff.
  3565.  
  3566. \item The documentation in the \LaTeX\ manual is excellent.
  3567. \Troff\/'s documentation is scattered over many references.
  3568. The documentation in the \TeX Book is very technical and the average reader
  3569. may find it unreadable.
  3570.  
  3571. \item At hanauma, we have a previewer for TeX on the SUN, but don't have it
  3572. for \troff.
  3573. \end{itemize}
  3574. \end{document}
  3575. SHAR_EOF
  3576. fi # end of overwriting check
  3577. #    End of shell archive
  3578. exit 0
  3579.  
  3580.